diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx
index 3608f00e3d..4e7e10b34c 100644
--- a/packages/cli/src/ui/components/InputPrompt.test.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.test.tsx
@@ -5332,6 +5332,34 @@ describe('InputPrompt', () => {
});
});
});
+
+ describe('terminal buffer rendering', () => {
+ it('does not clip the last char of a visual line whose width equals inputWidth', async () => {
+ const fullLine = '1234567890'; // 10 chars, exactly props.inputWidth
+ props.inputWidth = 10;
+ props.suggestionsWidth = 10;
+ vi.spyOn(props.config, 'getUseTerminalBuffer').mockReturnValue(true);
+ mockBuffer.text = fullLine;
+ mockBuffer.lines = [fullLine];
+ mockBuffer.allVisualLines = [fullLine];
+ mockBuffer.viewportVisualLines = [fullLine];
+ mockBuffer.visualToLogicalMap = [[0, 0]];
+ mockBuffer.visualToTransformedMap = [0];
+ mockBuffer.transformationsByLine = [[]];
+ mockBuffer.cursor = [0, fullLine.length];
+ mockBuffer.visualCursor = [0, fullLine.length];
+
+ const { lastFrame, unmount } = await renderWithProviders(
+ ,
+ { uiActions },
+ );
+
+ await waitFor(() => {
+ expect(clean(lastFrame())).toContain(fullLine);
+ });
+ unmount();
+ });
+ });
});
function clean(str: string | undefined): string {
diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx
index 67fefe0656..cd37e56abd 100644
--- a/packages/cli/src/ui/components/InputPrompt.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.tsx
@@ -93,6 +93,8 @@ import { useIsHelpDismissKey } from '../utils/shortcutsHelp.js';
import { useRepeatedKeyPress } from '../hooks/useRepeatedKeyPress.js';
import { useKeyMatchers } from '../hooks/useKeyMatchers.js';
+const SCROLLBAR_GUTTER_WIDTH = 1;
+
/**
* Returns if the terminal can be trusted to handle paste events atomically
* rather than potentially sending multiple paste events separated by line
@@ -1868,7 +1870,7 @@ export const InputPrompt: React.FC = ({
? `line-${item.absoluteVisualIdx}`
: `ghost-${item.index}`
}
- width={inputWidth}
+ width={inputWidth + SCROLLBAR_GUTTER_WIDTH}
backgroundColor={listBackgroundColor}
containerHeight={Math.min(
buffer.viewportHeight,
diff --git a/packages/cli/src/ui/components/__snapshots__/InputPrompt-InputPrompt-Highlighting-and-Cursor-Display-single-line-scenarios-should-display-cursor-correctly-at-the-end-of-the-line-2.snap.svg b/packages/cli/src/ui/components/__snapshots__/InputPrompt-InputPrompt-Highlighting-and-Cursor-Display-single-line-scenarios-should-display-cursor-correctly-at-the-end-of-the-line-2.snap.svg
new file mode 100644
index 0000000000..2f9e66a77a
--- /dev/null
+++ b/packages/cli/src/ui/components/__snapshots__/InputPrompt-InputPrompt-Highlighting-and-Cursor-Display-single-line-scenarios-should-display-cursor-correctly-at-the-end-of-the-line-2.snap.svg
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap
index db449ce4d7..04cba9385d 100644
--- a/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap
+++ b/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap
@@ -60,6 +60,12 @@ exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios >
────────────────────────────────────────────────────────────────────────────────────────────────────"
`;
+exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios > should display cursor correctly 'at the end of the line' 2`] = `
+"────────────────────────────────────────────────────────────────────────────────────────────────────
+ > hello
+────────────────────────────────────────────────────────────────────────────────────────────────────"
+`;
+
exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios > should display cursor correctly 'for multi-byte unicode characters' 1`] = `
"────────────────────────────────────────────────────────────────────────────────────────────────────
> hello 👍 world
@@ -168,6 +174,27 @@ exports[`InputPrompt > mouse interaction > should toggle paste expansion on doub
"
`;
+exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 4`] = `
+"▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
+ > [Pasted Text: 10 lines]
+▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
+"
+`;
+
+exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 5`] = `
+"▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
+ > [Pasted Text: 10 lines]
+▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
+"
+`;
+
+exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 6`] = `
+"▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
+ > [Pasted Text: 10 lines]
+▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
+"
+`;
+
exports[`InputPrompt > multiline rendering > should correctly render multiline input including blank lines 1`] = `
"────────────────────────────────────────────────────────────────────────────────────────────────────
> hello