From d45570a0fe4b5a2419db32e3aba0df02716b9bb3 Mon Sep 17 00:00:00 2001 From: dabaotongxue <297390763@qq.com> Date: Mon, 6 Jul 2026 22:50:26 +0800 Subject: [PATCH] fix(tui): highlight diff preview rows - Add themed backgrounds for added and removed diff rows - Separate diff line numbers from code with a gutter divider - Document new custom theme tokens for diff backgrounds --- .changeset/clear-diff-previews.md | 5 +++++ .../src/tui/components/media/diff-preview.ts | 18 ++++++++---------- apps/kimi-code/src/tui/theme/colors.ts | 8 ++++++++ apps/kimi-code/src/tui/theme/theme-schema.json | 2 ++ .../tui/components/media/diff-preview.test.ts | 14 ++++++++++---- docs/en/customization/themes.md | 2 ++ docs/zh/customization/themes.md | 2 ++ .../src/skill/builtin/custom-theme.md | 2 ++ .../test/skill/builtin-custom-theme.test.ts | 2 ++ 9 files changed, 41 insertions(+), 14 deletions(-) create mode 100644 .changeset/clear-diff-previews.md diff --git a/.changeset/clear-diff-previews.md b/.changeset/clear-diff-previews.md new file mode 100644 index 0000000000..e501fd4f76 --- /dev/null +++ b/.changeset/clear-diff-previews.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Add background highlighting to terminal diff previews. diff --git a/apps/kimi-code/src/tui/components/media/diff-preview.ts b/apps/kimi-code/src/tui/components/media/diff-preview.ts index 1fec48b267..c6005cc1a2 100644 --- a/apps/kimi-code/src/tui/components/media/diff-preview.ts +++ b/apps/kimi-code/src/tui/components/media/diff-preview.ts @@ -12,8 +12,8 @@ import { currentTheme } from '#/tui/theme'; export type DiffLineKind = 'context' | 'add' | 'delete'; interface DiffStyles { - add: (s: string) => string; - del: (s: string) => string; + addLine: (s: string) => string; + delLine: (s: string) => string; addBold: (s: string) => string; delBold: (s: string) => string; gutter: (s: string) => string; @@ -23,8 +23,8 @@ interface DiffStyles { function makeDiffStyles(): DiffStyles { const palette = currentTheme.palette; return { - add: (s) => chalk.hex(palette.diffAdded)(s), - del: (s) => chalk.hex(palette.diffRemoved)(s), + addLine: (s) => chalk.hex(palette.diffAdded).bgHex(palette.diffAddedBg)(s), + delLine: (s) => chalk.hex(palette.diffRemoved).bgHex(palette.diffRemovedBg)(s), addBold: (s) => chalk.bold.hex(palette.diffAddedStrong)(s), delBold: (s) => chalk.bold.hex(palette.diffRemovedStrong)(s), gutter: (s) => chalk.hex(palette.diffGutter)(s), @@ -134,9 +134,7 @@ export function renderDiffLines( : changedLines; for (const line of shown) { - const marker = line.kind === 'add' ? '+' : '-'; - const color = line.kind === 'add' ? s.add : s.del; - output.push(s.gutter(String(line.lineNum).padStart(4) + ' ') + color(marker + ' ' + line.code)); + output.push(formatDiffRow(line, s)); } const hidden = changedLines.length - shown.length; @@ -217,9 +215,9 @@ function buildClusters( } function formatDiffRow(line: DiffLine, s: DiffStyles): string { - const gutter = s.gutter(String(line.lineNum).padStart(4) + ' '); - if (line.kind === 'add') return gutter + s.add('+ ' + line.code); - if (line.kind === 'delete') return gutter + s.del('- ' + line.code); + const gutter = s.gutter(String(line.lineNum).padStart(4) + ' │ '); + if (line.kind === 'add') return gutter + s.addLine('+ ' + line.code); + if (line.kind === 'delete') return gutter + s.delLine('- ' + line.code); return gutter + ' ' + line.code; } diff --git a/apps/kimi-code/src/tui/theme/colors.ts b/apps/kimi-code/src/tui/theme/colors.ts index 66f9819c3e..25b93cc69b 100644 --- a/apps/kimi-code/src/tui/theme/colors.ts +++ b/apps/kimi-code/src/tui/theme/colors.ts @@ -56,8 +56,12 @@ export interface ColorPalette { // ── Diff (all consumed by components/media/diff-preview.ts) ── /** Added lines. */ diffAdded: string; + /** Added line background. */ + diffAddedBg: string; /** Removed lines. */ diffRemoved: string; + /** Removed line background. */ + diffRemovedBg: string; /** Added lines — intra-line changed words (bold). */ diffAddedStrong: string; /** Removed lines — intra-line changed words (bold). */ @@ -96,7 +100,9 @@ export const darkColors: ColorPalette = { error: '#E85454', diffAdded: '#4EC87E', + diffAddedBg: '#173326', diffRemoved: '#E85454', + diffRemovedBg: '#32181D', diffAddedStrong: '#7AD99B', diffRemovedStrong: '#F08585', diffGutter: '#6B6B6B', @@ -123,7 +129,9 @@ export const lightColors: ColorPalette = { error: '#B91C1C', diffAdded: '#0E7A38', + diffAddedBg: '#E8F5EE', diffRemoved: '#B91C1C', + diffRemovedBg: '#FDECEC', diffAddedStrong: '#0E7A38', diffRemovedStrong: '#B91C1C', diffGutter: '#737373', diff --git a/apps/kimi-code/src/tui/theme/theme-schema.json b/apps/kimi-code/src/tui/theme/theme-schema.json index a411088f9c..b7ca20ecb3 100644 --- a/apps/kimi-code/src/tui/theme/theme-schema.json +++ b/apps/kimi-code/src/tui/theme/theme-schema.json @@ -40,7 +40,9 @@ "warning": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Warning state color" }, "error": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Error state color" }, "diffAdded": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Diff added lines" }, + "diffAddedBg": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Diff added line background" }, "diffRemoved": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Diff removed lines" }, + "diffRemovedBg": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Diff removed line background" }, "diffAddedStrong": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Diff added lines (strong)" }, "diffRemovedStrong": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Diff removed lines (strong)" }, "diffGutter": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Diff gutter color" }, diff --git a/apps/kimi-code/test/tui/components/media/diff-preview.test.ts b/apps/kimi-code/test/tui/components/media/diff-preview.test.ts index d355bb7eda..3806121896 100644 --- a/apps/kimi-code/test/tui/components/media/diff-preview.test.ts +++ b/apps/kimi-code/test/tui/components/media/diff-preview.test.ts @@ -165,10 +165,16 @@ describe('renderDiffLinesClustered', () => { ); // Context lines keep the new (post-edit) line numbers from newStart; // deleted lines use oldStart; added lines use newStart. - expect(text).toContain(' 20 A'); - expect(text).toContain(' 11 - B'); - expect(text).toContain(' 21 + X'); - expect(text).toContain(' 22 C'); + expect(text).toContain(' 20 │ A'); + expect(text).toContain(' 11 │ - B'); + expect(text).toContain(' 21 │ + X'); + expect(text).toContain(' 22 │ C'); + }); + + it('renders a clear sign column between the gutter and code', () => { + const text = stripAnsi(renderDiffLinesClustered('old', 'new', 'f.ts').join('\n')); + expect(text).toContain(' 1 │ - old'); + expect(text).toContain(' 1 │ + new'); }); it('truncates at cluster boundary and appends the ctrl+o footer when maxLines is set', () => { diff --git a/docs/en/customization/themes.md b/docs/en/customization/themes.md index 82e0e55dfd..e73824f340 100644 --- a/docs/en/customization/themes.md +++ b/docs/en/customization/themes.md @@ -20,7 +20,9 @@ Custom themes can override the tokens below. The `dark` and `light` columns show | `warning` | `#E8A838` | `#92660A` | Warning state. auto/yolo badges, stale markers, Plan mode hint | | `error` | `#E85454` | `#B91C1C` | Error state. Error messages, failed tool output | | `diffAdded` | `#4EC87E` | `#0E7A38` | Diff added lines | +| `diffAddedBg` | `#173326` | `#E8F5EE` | Diff added line background | | `diffRemoved` | `#E85454` | `#B91C1C` | Diff removed lines | +| `diffRemovedBg` | `#32181D` | `#FDECEC` | Diff removed line background | | `diffAddedStrong` | `#7AD99B` | `#0E7A38` | Diff intra-line changed words, added and bold | | `diffRemovedStrong` | `#F08585` | `#B91C1C` | Diff intra-line changed words, removed and bold | | `diffGutter` | `#6B6B6B` | `#737373` | Diff line-number gutter | diff --git a/docs/zh/customization/themes.md b/docs/zh/customization/themes.md index 778863bbfa..8c5d99220d 100644 --- a/docs/zh/customization/themes.md +++ b/docs/zh/customization/themes.md @@ -20,7 +20,9 @@ Kimi Code CLI 可以使用内置配色,也可以使用自定义 JSON 主题文 | `warning` | `#E8A838` | `#92660A` | 警告态。auto/yolo 徽章、过期标记、Plan 模式提示 | | `error` | `#E85454` | `#B91C1C` | 错误态。错误信息、失败的工具输出 | | `diffAdded` | `#4EC87E` | `#0E7A38` | diff 新增行 | +| `diffAddedBg` | `#173326` | `#E8F5EE` | diff 新增行背景 | | `diffRemoved` | `#E85454` | `#B91C1C` | diff 删除行 | +| `diffRemovedBg` | `#32181D` | `#FDECEC` | diff 删除行背景 | | `diffAddedStrong` | `#7AD99B` | `#0E7A38` | diff 行内改动的新增词(加粗高亮) | | `diffRemovedStrong` | `#F08585` | `#B91C1C` | diff 行内改动的删除词(加粗高亮) | | `diffGutter` | `#6B6B6B` | `#737373` | diff 行号槽 | diff --git a/packages/agent-core/src/skill/builtin/custom-theme.md b/packages/agent-core/src/skill/builtin/custom-theme.md index 37a5bdfb4e..74cd8c734d 100644 --- a/packages/agent-core/src/skill/builtin/custom-theme.md +++ b/packages/agent-core/src/skill/builtin/custom-theme.md @@ -73,7 +73,9 @@ Only set tokens from this set — unknown keys are silently ignored at load. If | `warning` | Warning state: auto/yolo badges, stale markers, plan-mode hint | | `error` | Error state: error messages, failed tool output | | `diffAdded` | Diff added lines | +| `diffAddedBg` | Diff added line background | | `diffRemoved` | Diff removed lines | +| `diffRemovedBg` | Diff removed line background | | `diffAddedStrong` | Diff intra-line changed words, added (bold) | | `diffRemovedStrong` | Diff intra-line changed words, removed (bold) | | `diffGutter` | Diff line-number gutter | diff --git a/packages/agent-core/test/skill/builtin-custom-theme.test.ts b/packages/agent-core/test/skill/builtin-custom-theme.test.ts index a0e88248e4..52bbfdc307 100644 --- a/packages/agent-core/test/skill/builtin-custom-theme.test.ts +++ b/packages/agent-core/test/skill/builtin-custom-theme.test.ts @@ -34,7 +34,9 @@ describe('builtin skill: custom-theme', () => { 'warning', 'error', 'diffAdded', + 'diffAddedBg', 'diffRemoved', + 'diffRemovedBg', 'diffAddedStrong', 'diffRemovedStrong', 'diffGutter',