diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 2a79620e..26a3f795 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -864,18 +864,21 @@ function generateSyntax(theme: Theme) { scope: ["diff.plus"], style: { foreground: theme.diffAdded, + background: theme.diffAddedBg, }, }, { scope: ["diff.minus"], style: { foreground: theme.diffRemoved, + background: theme.diffRemovedBg, }, }, { scope: ["diff.delta"], style: { foreground: theme.diffContext, + background: theme.diffContextBg, }, }, { diff --git a/packages/opencode/src/snapshot/index.ts b/packages/opencode/src/snapshot/index.ts index e8500e09..c71a1b67 100644 --- a/packages/opencode/src/snapshot/index.ts +++ b/packages/opencode/src/snapshot/index.ts @@ -24,6 +24,8 @@ export namespace Snapshot { }) .quiet() .nothrow() + // Configure git to not convert line endings on Windows + await $`git --git-dir ${git} config core.autocrlf false`.quiet().nothrow() log.info("initialized") } await $`git --git-dir ${git} --work-tree ${Instance.worktree} add .`.quiet().cwd(Instance.directory).nothrow() @@ -45,10 +47,11 @@ export namespace Snapshot { export async function patch(hash: string): Promise { const git = gitdir() await $`git --git-dir ${git} --work-tree ${Instance.worktree} add .`.quiet().cwd(Instance.directory).nothrow() - const result = await $`git --git-dir ${git} --work-tree ${Instance.worktree} diff --name-only ${hash} -- .` - .quiet() - .cwd(Instance.directory) - .nothrow() + const result = + await $`git -c core.autocrlf=false --git-dir ${git} --work-tree ${Instance.worktree} diff --name-only ${hash} -- .` + .quiet() + .cwd(Instance.directory) + .nothrow() // If git diff fails, return empty patch if (result.exitCode !== 0) { @@ -122,10 +125,11 @@ export namespace Snapshot { export async function diff(hash: string) { const git = gitdir() await $`git --git-dir ${git} --work-tree ${Instance.worktree} add .`.quiet().cwd(Instance.directory).nothrow() - const result = await $`git --git-dir ${git} --work-tree ${Instance.worktree} diff ${hash} -- .` - .quiet() - .cwd(Instance.worktree) - .nothrow() + const result = + await $`git -c core.autocrlf=false --git-dir ${git} --work-tree ${Instance.worktree} diff ${hash} -- .` + .quiet() + .cwd(Instance.worktree) + .nothrow() if (result.exitCode !== 0) { log.warn("failed to get diff", { @@ -155,7 +159,7 @@ export namespace Snapshot { export async function diffFull(from: string, to: string): Promise { const git = gitdir() const result: FileDiff[] = [] - for await (const line of $`git --git-dir ${git} --work-tree ${Instance.worktree} diff --no-renames --numstat ${from} ${to} -- .` + for await (const line of $`git -c core.autocrlf=false --git-dir ${git} --work-tree ${Instance.worktree} diff --no-renames --numstat ${from} ${to} -- .` .quiet() .cwd(Instance.directory) .nothrow() @@ -165,10 +169,16 @@ export namespace Snapshot { const isBinaryFile = additions === "-" && deletions === "-" const before = isBinaryFile ? "" - : await $`git --git-dir ${git} --work-tree ${Instance.worktree} show ${from}:${file}`.quiet().nothrow().text() + : await $`git -c core.autocrlf=false --git-dir ${git} --work-tree ${Instance.worktree} show ${from}:${file}` + .quiet() + .nothrow() + .text() const after = isBinaryFile ? "" - : await $`git --git-dir ${git} --work-tree ${Instance.worktree} show ${to}:${file}`.quiet().nothrow().text() + : await $`git -c core.autocrlf=false --git-dir ${git} --work-tree ${Instance.worktree} show ${to}:${file}` + .quiet() + .nothrow() + .text() result.push({ file, before, diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts index 96c62b86..ca985937 100644 --- a/packages/opencode/src/tool/edit.ts +++ b/packages/opencode/src/tool/edit.ts @@ -18,6 +18,10 @@ import { Instance } from "../project/instance" import { Agent } from "../agent/agent" import { Snapshot } from "@/snapshot" +function normalizeLineEndings(text: string): string { + return text.replaceAll("\r\n", "\n") +} + export const EditTool = Tool.define("edit", { description: DESCRIPTION, parameters: z.object({ @@ -91,7 +95,9 @@ export const EditTool = Tool.define("edit", { contentOld = await file.text() contentNew = replace(contentOld, params.oldString, params.newString, params.replaceAll) - diff = trimDiff(createTwoFilesPatch(filePath, filePath, contentOld, contentNew)) + diff = trimDiff( + createTwoFilesPatch(filePath, filePath, normalizeLineEndings(contentOld), normalizeLineEndings(contentNew)), + ) if (agent.permission.edit === "ask") { await Permission.ask({ type: "edit", @@ -111,7 +117,9 @@ export const EditTool = Tool.define("edit", { file: filePath, }) contentNew = await file.text() - diff = trimDiff(createTwoFilesPatch(filePath, filePath, contentOld, contentNew)) + diff = trimDiff( + createTwoFilesPatch(filePath, filePath, normalizeLineEndings(contentOld), normalizeLineEndings(contentNew)), + ) })() FileTime.read(ctx.sessionID, filePath)