mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
Update diff colors (#4747)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user