Fix syntax highlighting and rendering issues. (#7759)

Co-authored-by: Miguel Solorio <miguelsolorio@google.com>
This commit is contained in:
Jacob Richman
2025-09-05 15:29:54 -07:00
committed by GitHub
parent c1b8708ef5
commit d8dbe6271f
4 changed files with 120 additions and 45 deletions

View File

@@ -1311,6 +1311,33 @@ describe('InputPrompt', () => {
});
});
describe('multiline rendering', () => {
it('should correctly render multiline input including blank lines', async () => {
const text = 'hello\n\nworld';
mockBuffer.text = text;
mockBuffer.lines = text.split('\n');
mockBuffer.viewportVisualLines = text.split('\n');
mockBuffer.allVisualLines = text.split('\n');
mockBuffer.visualCursor = [2, 5]; // cursor at the end of "world"
const { stdout, unmount } = renderWithProviders(
<InputPrompt {...props} />,
);
await wait();
const frame = stdout.lastFrame();
// Check that all lines, including the empty one, are rendered.
// This implicitly tests that the Box wrapper provides height for the empty line.
expect(frame).toContain('hello');
expect(frame).toContain(`world${chalk.inverse(' ')}`);
const outputLines = frame!.split('\n');
// The number of lines should be 2 for the border plus 3 for the content.
expect(outputLines.length).toBe(5);
unmount();
});
});
describe('multiline paste', () => {
it.each([
{

View File

@@ -723,7 +723,10 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
) : (
linesToRender
.map((lineText, visualIdxInRenderedSet) => {
const tokens = parseInputForHighlighting(lineText);
const tokens = parseInputForHighlighting(
lineText,
visualIdxInRenderedSet,
);
const cursorVisualRow =
cursorVisualRowAbsolute - scrollVisualRow;
const isOnCursorLine =
@@ -784,7 +787,9 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
) {
if (!currentLineGhost) {
renderedLine.push(
<Text key="cursor-end">{chalk.inverse(' ')}</Text>,
<Text key={`cursor-end-${cursorVisualColAbsolute}`}>
{chalk.inverse(' ')}
</Text>,
);
}
}
@@ -796,15 +801,17 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
currentLineGhost;
return (
<Text key={`line-${visualIdxInRenderedSet}`}>
{renderedLine}
{showCursorBeforeGhost && chalk.inverse(' ')}
{currentLineGhost && (
<Text color={theme.text.secondary}>
{currentLineGhost}
</Text>
)}
</Text>
<Box key={`line-${visualIdxInRenderedSet}`} height={1}>
<Text>
{renderedLine}
{showCursorBeforeGhost && chalk.inverse(' ')}
{currentLineGhost && (
<Text color={theme.text.secondary}>
{currentLineGhost}
</Text>
)}
</Text>
</Box>
);
})
.concat(