дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 03:05:40 +02:00
feat(vcs): Accept a diff change from the keyboard and step between diff files (#158)
- Accept Left Side / Accept Right Side copy the change at the caret to the other side of a side-by-side diff (⌃⌘→ / ⌃⌘← on macOS, Ctrl+Alt+R / Ctrl+Alt+A on Windows). - Compare Next File / Compare Previous File open the neighbouring file of the diff chain directly (⌃⇧→ / ⌃⇧← on macOS, Alt+Shift+→ / ← on Windows).
Цей коміт міститься в:
1 джерело
cfd2970531
коміт
b35035f8d9
9 files changed
+80
-7
No files matched your search
@@ -66,6 +66,7 @@ describe("Download JDK dialog", () => {
|
||||
it("preselects the version a fix asks for", async () => {
|
||||
render(<DownloadJdkDialog initialVersion={21} onClose={() => {}} onDownloaded={() => {}} />);
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "Download" })).toBeEnabled());
|
||||
expect(screen.getByRole("button", { name: "Version" })).toHaveTextContent("21");
|
||||
// The version list loads after the Download button enables on a busy runner.
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "Version" })).toHaveTextContent("21"));
|
||||
});
|
||||
});
|
||||
@@ -24,7 +24,7 @@ import { tx } from "@/platform/i18n";
|
||||
import { IconButton, Select, Spinner, T } from "@/ui";
|
||||
import { editorService, type EditorInput } from "@/workbench/contributions";
|
||||
import { languageFor, viewerBase } from "./cm";
|
||||
import { applyChunk, arrowControls, hoverRevert } from "./diffControls";
|
||||
import { applyChunk, arrowControls, chunkAt, hoverRevert } from "./diffControls";
|
||||
import {
|
||||
HIGHLIGHT_OPTIONS,
|
||||
IGNORE_OPTIONS,
|
||||
@@ -586,10 +586,26 @@ export function DiffEditor({ input }: { input: EditorInput }) {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const nav = useRef<DiffNavigator>({ next: () => step(1), prev: () => step(-1), jumpToSource });
|
||||
/** ⌃⌘→ / ⌃⌘←: the change at the caret applied toward the other, editable side. */
|
||||
const applyChange = (source: "a" | "b") => {
|
||||
const views = viewsRef.current;
|
||||
const merge = views?.merge;
|
||||
if (!merge || !views.a || !(source === "a" ? editableB : editableA)) return false;
|
||||
const side = focusedSide.current;
|
||||
const view = side === "a" ? views.a : views.b;
|
||||
const index = chunkAt(merge.chunks, side, view.state.selection.main.head, view.state.doc.length);
|
||||
if (index < 0) return false;
|
||||
applyChunk(merge, index, source);
|
||||
return true;
|
||||
};
|
||||
const file = (dir: 1 | -1) => {
|
||||
const neighbour = chainNeighbour(data, dir);
|
||||
if (neighbour) void openDiff(neighbour, { preview: true });
|
||||
};
|
||||
const nav = useRef<DiffNavigator>({ next: () => step(1), prev: () => step(-1), jumpToSource, applyChange, file });
|
||||
useEffect(() => {
|
||||
nav.current = { next: () => step(1), prev: () => step(-1), jumpToSource };
|
||||
}, [step, jumpToSource]);
|
||||
nav.current = { next: () => step(1), prev: () => step(-1), jumpToSource, applyChange, file };
|
||||
});
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
|
||||
@@ -125,6 +125,40 @@ export function registerCompareActions(): () => void {
|
||||
when: "diffEditorFocus",
|
||||
run: () => focusedDiffNavigator()?.prev(),
|
||||
},
|
||||
{
|
||||
id: "diff.nextFile",
|
||||
title: "Compare Next File",
|
||||
category: "Diff",
|
||||
icon: "arrow-right",
|
||||
when: "diffEditorFocus",
|
||||
run: () => focusedDiffNavigator()?.file(1),
|
||||
},
|
||||
{
|
||||
id: "diff.prevFile",
|
||||
title: "Compare Previous File",
|
||||
category: "Diff",
|
||||
icon: "arrow-left",
|
||||
when: "diffEditorFocus",
|
||||
run: () => focusedDiffNavigator()?.file(-1),
|
||||
},
|
||||
{
|
||||
id: "diff.applyLeftSide",
|
||||
title: "Accept Left Side",
|
||||
description: "Copies the change at the caret from the left side to the right one",
|
||||
category: "Diff",
|
||||
icon: "arrow-right",
|
||||
when: "diffEditorFocus",
|
||||
run: () => void focusedDiffNavigator()?.applyChange("a"),
|
||||
},
|
||||
{
|
||||
id: "diff.applyRightSide",
|
||||
title: "Accept Right Side",
|
||||
description: "Copies the change at the caret from the right side to the left one",
|
||||
category: "Diff",
|
||||
icon: "arrow-left",
|
||||
when: "diffEditorFocus",
|
||||
run: () => void focusedDiffNavigator()?.applyChange("b"),
|
||||
},
|
||||
{
|
||||
id: "diff.jumpToSource",
|
||||
title: "Jump to Source",
|
||||
|
||||
@@ -84,7 +84,7 @@ class RevertWidget extends WidgetType {
|
||||
}
|
||||
}
|
||||
|
||||
function chunkAt(chunks: readonly Chunk[], side: "a" | "b", pos: number, docLength: number): number {
|
||||
export function chunkAt(chunks: readonly Chunk[], side: "a" | "b", pos: number, docLength: number): number {
|
||||
return chunks.findIndex((c) => {
|
||||
const [from, to] = side === "a" ? [c.fromA, c.toA] : [c.fromB, c.toB];
|
||||
return from === to ? pos === from : pos >= from && pos < Math.max(to, from + 1) && pos <= docLength;
|
||||
|
||||
@@ -4,6 +4,10 @@ export interface DiffNavigator {
|
||||
next(): void;
|
||||
prev(): void;
|
||||
jumpToSource(): void;
|
||||
/** Apply the change at the caret from the left side to the right (`a`) or back (`b`). */
|
||||
applyChange(source: "a" | "b"): boolean;
|
||||
/** Open the next / previous file of the diff chain (changes of a commit or change list). */
|
||||
file(dir: 1 | -1): void;
|
||||
}
|
||||
|
||||
let focused: DiffNavigator | null = null;
|
||||
|
||||
Reference in new issue
Заблокувати користувача