summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/components
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/components')
-rw-r--r--packages/cli/src/ui/components/InputPrompt.test.tsx37
-rw-r--r--packages/cli/src/ui/components/InputPrompt.tsx6
-rw-r--r--packages/cli/src/ui/components/shared/text-buffer.ts7
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' ||