diff options
| author | Miguel Solorio <[email protected]> | 2025-07-23 15:39:22 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-23 22:39:22 +0000 |
| commit | 2e28bb90a00ad415d453a2ec868faa78679602f0 (patch) | |
| tree | e94a960be7d61a0982ba4e997442a6afeda63082 /packages/cli/src/ui/components | |
| parent | e21b5c95aaf801da2539ebbc53f0fd3cf45b7ed2 (diff) | |
Update diff colors (#4747)
Co-authored-by: Jacob Richman <[email protected]>
Diffstat (limited to 'packages/cli/src/ui/components')
3 files changed, 69 insertions, 44 deletions
diff --git a/packages/cli/src/ui/components/ThemeDialog.tsx b/packages/cli/src/ui/components/ThemeDialog.tsx index a6a16b8c..7c38bb4b 100644 --- a/packages/cli/src/ui/components/ThemeDialog.tsx +++ b/packages/cli/src/ui/components/ThemeDialog.tsx @@ -279,18 +279,23 @@ export function ThemeDialog({ > {colorizeCode( `# function --def fibonacci(n): -- a, b = 0, 1 -- for _ in range(n): -- a, b = b, a + b -- return a`, +def fibonacci(n): + a, b = 0, 1 + for _ in range(n): + a, b = b, a + b + return a`, 'python', codeBlockHeight, colorizeCodeWidth, )} <Box marginTop={1} /> <DiffRenderer - diffContent={`--- a/old_file.txt\n+++ b/new_file.txt\n@@ -1,6 +1,7 @@\n # function\n-def fibonacci(n):\n- a, b = 0, 1\n- for _ in range(n):\n- a, b = b, a + b\n- return a\n+def fibonacci(n):\n+ a, b = 0, 1\n+ for _ in range(n):\n+ a, b = b, a + b\n+ return a\n+\n+print(fibonacci(10))\n`} + diffContent={`--- a/util.py ++++ b/util.py +@@ -1,2 +1,2 @@ +- print("Hello, " + name) ++ print(f"Hello, {name}!") +`} availableTerminalHeight={diffHeight} terminalWidth={colorizeCodeWidth} theme={previewTheme} diff --git a/packages/cli/src/ui/components/messages/DiffRenderer.test.tsx b/packages/cli/src/ui/components/messages/DiffRenderer.test.tsx index e299f2af..9629b94b 100644 --- a/packages/cli/src/ui/components/messages/DiffRenderer.test.tsx +++ b/packages/cli/src/ui/components/messages/DiffRenderer.test.tsx @@ -130,8 +130,8 @@ index 0000001..0000002 100644 ); const output = lastFrame(); const lines = output!.split('\n'); - expect(lines[0]).toBe('1 - old line'); - expect(lines[1]).toBe('1 + new line'); + expect(lines[0]).toBe('1 - old line'); + expect(lines[1]).toBe('1 + new line'); }); it('should handle diff with only header and no changes', () => { @@ -253,35 +253,35 @@ index 123..789 100644 { terminalWidth: 80, height: undefined, - expected: `1 console.log('first hunk'); -2 - const oldVar = 1; -2 + const newVar = 1; -3 console.log('end of first hunk'); + expected: ` 1 console.log('first hunk'); + 2 - const oldVar = 1; + 2 + const newVar = 1; + 3 console.log('end of first hunk'); ════════════════════════════════════════════════════════════════════════════════ -20 console.log('second hunk'); -21 - const anotherOld = 'test'; -21 + const anotherNew = 'test'; -22 console.log('end of second hunk');`, +20 console.log('second hunk'); +21 - const anotherOld = 'test'; +21 + const anotherNew = 'test'; +22 console.log('end of second hunk');`, }, { terminalWidth: 80, height: 6, expected: `... first 4 lines hidden ... ════════════════════════════════════════════════════════════════════════════════ -20 console.log('second hunk'); -21 - const anotherOld = 'test'; -21 + const anotherNew = 'test'; -22 console.log('end of second hunk');`, +20 console.log('second hunk'); +21 - const anotherOld = 'test'; +21 + const anotherNew = 'test'; +22 console.log('end of second hunk');`, }, { terminalWidth: 30, height: 6, expected: `... first 10 lines hidden ... - 'test'; -21 + const anotherNew = - 'test'; -22 console.log('end of - second hunk');`, + ; +21 + const anotherNew = 'test' + ; +22 console.log('end of + second hunk');`, }, ])( 'with terminalWidth $terminalWidth and height $height', @@ -329,11 +329,11 @@ fileDiff Index: file.txt ); const output = lastFrame(); - expect(output).toEqual(`1 - const oldVar = 1; -1 + const newVar = 1; + expect(output).toEqual(` 1 - const oldVar = 1; + 1 + const newVar = 1; ════════════════════════════════════════════════════════════════════════════════ -20 - const anotherOld = 'test'; -20 + const anotherNew = 'test';`); +20 - const anotherOld = 'test'; +20 + const anotherNew = 'test';`); }); it('should correctly render a new file with no file extension correctly', () => { diff --git a/packages/cli/src/ui/components/messages/DiffRenderer.tsx b/packages/cli/src/ui/components/messages/DiffRenderer.tsx index db402517..7f130b3f 100644 --- a/packages/cli/src/ui/components/messages/DiffRenderer.tsx +++ b/packages/cli/src/ui/components/messages/DiffRenderer.tsx @@ -8,7 +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'; +import { colorizeCode, colorizeLine } from '../../utils/CodeColorizer.js'; import { MaxSizedBox } from '../shared/MaxSizedBox.js'; interface DiffLine { @@ -157,7 +157,6 @@ export const DiffRenderer: React.FC<DiffRendererProps> = ({ tabWidth, availableTerminalHeight, terminalWidth, - theme, ); } @@ -170,7 +169,6 @@ const renderDiffContent = ( tabWidth = DEFAULT_TAB_WIDTH, availableTerminalHeight: number | undefined, terminalWidth: number, - theme?: import('../../themes/theme.js').Theme, ) => { // 1. Normalize whitespace (replace tabs with spaces) *before* further processing const normalizedLines = parsedLines.map((line) => ({ @@ -191,6 +189,18 @@ const renderDiffContent = ( ); } + const maxLineNumber = Math.max( + 0, + ...displayableLines.map((l) => l.oldLine ?? 0), + ...displayableLines.map((l) => l.newLine ?? 0), + ); + const gutterWidth = Math.max(1, maxLineNumber.toString().length); + + const fileExtension = filename?.split('.').pop() || null; + const language = fileExtension + ? getLanguageFromExtension(fileExtension) + : null; + // Calculate the minimum indentation across all displayable lines let baseIndentation = Infinity; // Start high to find the minimum for (const line of displayableLines) { @@ -237,27 +247,25 @@ const renderDiffContent = ( ) { acc.push( <Box key={`gap-${index}`}> - <Text wrap="truncate">{'═'.repeat(terminalWidth)}</Text> + <Text wrap="truncate" color={Colors.Gray}> + {'═'.repeat(terminalWidth)} + </Text> </Box>, ); } const lineKey = `diff-line-${index}`; let gutterNumStr = ''; - let color: string | undefined = undefined; let prefixSymbol = ' '; - let dim = false; switch (line.type) { case 'add': gutterNumStr = (line.newLine ?? '').toString(); - color = theme?.colors?.AccentGreen || 'green'; prefixSymbol = '+'; lastLineNumber = line.newLine ?? null; break; case 'del': gutterNumStr = (line.oldLine ?? '').toString(); - color = theme?.colors?.AccentRed || 'red'; prefixSymbol = '-'; // For deletions, update lastLineNumber based on oldLine if it's advancing. // This helps manage gaps correctly if there are multiple consecutive deletions @@ -268,7 +276,6 @@ const renderDiffContent = ( break; case 'context': gutterNumStr = (line.newLine ?? '').toString(); - dim = true; prefixSymbol = ' '; lastLineNumber = line.newLine ?? null; break; @@ -280,13 +287,26 @@ const renderDiffContent = ( acc.push( <Box key={lineKey} flexDirection="row"> - <Text color={Colors.Gray}>{gutterNumStr.padEnd(4)} </Text> - <Text color={color} dimColor={dim}> - {prefixSymbol}{' '} - </Text> - <Text color={color} dimColor={dim} wrap="wrap"> - {displayContent} + <Text color={Colors.Gray}> + {gutterNumStr.padStart(gutterWidth)}{' '} </Text> + {line.type === 'context' ? ( + <> + <Text>{prefixSymbol} </Text> + <Text wrap="wrap"> + {colorizeLine(displayContent, language)} + </Text> + </> + ) : ( + <Text + backgroundColor={ + line.type === 'add' ? Colors.DiffAdded : Colors.DiffRemoved + } + wrap="wrap" + > + {prefixSymbol} {colorizeLine(displayContent, language)} + </Text> + )} </Box>, ); return acc; |
