feat(cli): Improve new file diff rendering with syntax highlighting
- Enhance the component to provide better readability for newly created files. - Instead of displaying a standard line-by-line diff for new files, extract the added content and render it with syntax highlighting based on the file extension. - Refactor the existing diff rendering logic into a separate function. - Add a helper function to map common file extensions to language names for syntax highlighting. Fixes: https://b.corp.google.com/issues/414279447 Signed-off-by: Gemini, your friendly neighborhood code agent.
This commit is contained in:
parent
a6e9bcb52d
commit
a9dc2772dd
|
@ -8,6 +8,7 @@ import React from 'react';
|
|||
import { Box, Text } from 'ink';
|
||||
import { Colors } from '../../colors.js';
|
||||
import crypto from 'crypto';
|
||||
import { colorizeCode } from '../../utils/CodeColorizer.js';
|
||||
|
||||
interface DiffLine {
|
||||
type: 'add' | 'del' | 'context' | 'hunk' | 'other';
|
||||
|
@ -104,6 +105,42 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
|||
|
||||
const parsedLines = parseDiffWithLineNumbers(diffContent);
|
||||
|
||||
// Check if the diff represents a new file (only additions and header lines)
|
||||
const isNewFile = parsedLines.every(
|
||||
(line) =>
|
||||
line.type === 'add' ||
|
||||
line.type === 'hunk' ||
|
||||
line.type === 'other' ||
|
||||
line.content.startsWith('diff --git') ||
|
||||
line.content.startsWith('new file mode'),
|
||||
);
|
||||
|
||||
let renderedOutput;
|
||||
|
||||
if (isNewFile) {
|
||||
// Extract only the added lines' content
|
||||
const addedContent = parsedLines
|
||||
.filter((line) => line.type === 'add')
|
||||
.map((line) => line.content)
|
||||
.join('\n');
|
||||
// Attempt to infer language from filename, default to plain text if no filename
|
||||
const fileExtension = filename?.split('.').pop() || null;
|
||||
const language = fileExtension
|
||||
? getLanguageFromExtension(fileExtension)
|
||||
: null;
|
||||
renderedOutput = colorizeCode(addedContent, language);
|
||||
} else {
|
||||
renderedOutput = renderDiffContent(parsedLines, filename, tabWidth);
|
||||
}
|
||||
|
||||
return renderedOutput;
|
||||
};
|
||||
|
||||
const renderDiffContent = (
|
||||
parsedLines: DiffLine[],
|
||||
filename?: string,
|
||||
tabWidth = DEFAULT_TAB_WIDTH,
|
||||
) => {
|
||||
// 1. Normalize whitespace (replace tabs with spaces) *before* further processing
|
||||
const normalizedLines = parsedLines.map((line) => ({
|
||||
...line,
|
||||
|
@ -137,11 +174,11 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
|||
if (!isFinite(baseIndentation)) {
|
||||
baseIndentation = 0;
|
||||
}
|
||||
// --- End Modification ---
|
||||
|
||||
const key = filename
|
||||
? `diff-box-${filename}`
|
||||
: `diff-box-${crypto.createHash('sha1').update(diffContent).digest('hex')}`;
|
||||
: `diff-box-${crypto.createHash('sha1').update(JSON.stringify(parsedLines)).digest('hex')}`;
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" key={key}>
|
||||
{/* Iterate over the lines that should be displayed (already normalized) */}
|
||||
|
@ -193,3 +230,19 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({
|
|||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const getLanguageFromExtension = (extension: string): string | null => {
|
||||
const languageMap: { [key: string]: string } = {
|
||||
'.js': 'javascript',
|
||||
'.ts': 'typescript',
|
||||
'.py': 'python',
|
||||
'.json': 'json',
|
||||
'.css': 'css',
|
||||
'.html': 'html',
|
||||
'.sh': 'bash',
|
||||
'.md': 'markdown',
|
||||
'.yaml': 'yaml',
|
||||
'.yml': 'yaml',
|
||||
};
|
||||
return languageMap[extension] || null; // Return null if extension not found
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue