summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/components
diff options
context:
space:
mode:
authorMiguel Solorio <[email protected]>2025-07-23 15:39:22 -0700
committerGitHub <[email protected]>2025-07-23 22:39:22 +0000
commit2e28bb90a00ad415d453a2ec868faa78679602f0 (patch)
treee94a960be7d61a0982ba4e997442a6afeda63082 /packages/cli/src/ui/components
parente21b5c95aaf801da2539ebbc53f0fd3cf45b7ed2 (diff)
Update diff colors (#4747)
Co-authored-by: Jacob Richman <[email protected]>
Diffstat (limited to 'packages/cli/src/ui/components')
-rw-r--r--packages/cli/src/ui/components/ThemeDialog.tsx17
-rw-r--r--packages/cli/src/ui/components/messages/DiffRenderer.test.tsx46
-rw-r--r--packages/cli/src/ui/components/messages/DiffRenderer.tsx50
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;