diff options
Diffstat (limited to 'packages/cli/src/ui/components')
| -rw-r--r-- | packages/cli/src/ui/components/InputPrompt.test.tsx | 37 | ||||
| -rw-r--r-- | packages/cli/src/ui/components/InputPrompt.tsx | 6 | ||||
| -rw-r--r-- | packages/cli/src/ui/components/shared/text-buffer.ts | 7 |
3 files changed, 50 insertions, 0 deletions
diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx index a4aaf6e9..11a0eb48 100644 --- a/packages/cli/src/ui/components/InputPrompt.test.tsx +++ b/packages/cli/src/ui/components/InputPrompt.test.tsx @@ -1211,6 +1211,43 @@ describe('InputPrompt', () => { }); }); + describe('multiline paste', () => { + it.each([ + { + description: 'with \n newlines', + pastedText: 'This \n is \n a \n multiline \n paste.', + }, + { + description: 'with extra slashes before \n newlines', + pastedText: 'This \\\n is \\\n a \\\n multiline \\\n paste.', + }, + { + description: 'with \r\n newlines', + pastedText: 'This\r\nis\r\na\r\nmultiline\r\npaste.', + }, + ])('should handle multiline paste $description', async ({ pastedText }) => { + const { stdin, unmount } = renderWithProviders( + <InputPrompt {...props} />, + ); + await wait(); + + // Simulate a bracketed paste event from the terminal + stdin.write(`\x1b[200~${pastedText}\x1b[201~`); + await wait(); + + // Verify that the buffer's handleInput was called once with the full text + expect(props.buffer.handleInput).toHaveBeenCalledTimes(1); + expect(props.buffer.handleInput).toHaveBeenCalledWith( + expect.objectContaining({ + paste: true, + sequence: pastedText, + }), + ); + + unmount(); + }); + }); + describe('enhanced input UX - double ESC clear functionality', () => { it('should clear buffer on second ESC press', async () => { const onEscapePromptChange = vi.fn(); diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx index dcfdace3..99a59c34 100644 --- a/packages/cli/src/ui/components/InputPrompt.tsx +++ b/packages/cli/src/ui/components/InputPrompt.tsx @@ -239,6 +239,12 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ return; } + if (key.paste) { + // Ensure we never accidentally interpret paste as regular input. + buffer.handleInput(key); + return; + } + if (vimHandleInput && vimHandleInput(key)) { return; } diff --git a/packages/cli/src/ui/components/shared/text-buffer.ts b/packages/cli/src/ui/components/shared/text-buffer.ts index 84bbdc9b..93f6e360 100644 --- a/packages/cli/src/ui/components/shared/text-buffer.ts +++ b/packages/cli/src/ui/components/shared/text-buffer.ts @@ -1833,6 +1833,13 @@ export function useTextBuffer({ }): void => { const { sequence: input } = key; + if (key.paste) { + // Do not do any other processing on pastes so ensure we handle them + // before all other cases. + insert(input, { paste: key.paste }); + return; + } + if ( key.name === 'return' || input === '\r' || |
