Skip to content

Commit 990ba4a

Browse files
committed
fix: restore cursor position after applying diffs
Fixes #6853 - When Roo applies diffs to a file, the cursor/scroll position is now preserved instead of jumping to the top of the file. Changes: - Added savedCursorPosition and savedVisibleRanges properties to DiffViewProvider - Capture cursor position and visible ranges before opening diff view - Restore cursor position and visible ranges after saving changes - Also restore position when reverting changes or using saveDirectly method
1 parent ad0e33e commit 990ba4a

File tree

1 file changed

+71
-3
lines changed

1 file changed

+71
-3
lines changed

src/integrations/editor/DiffViewProvider.ts

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export class DiffViewProvider {
3737
private streamedLines: string[] = []
3838
private preDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = []
3939
private taskRef: WeakRef<Task>
40+
private savedCursorPosition?: vscode.Position
41+
private savedVisibleRanges?: vscode.Range[]
4042

4143
constructor(
4244
private cwd: string,
@@ -51,6 +53,13 @@ export class DiffViewProvider {
5153
const absolutePath = path.resolve(this.cwd, relPath)
5254
this.isEditing = true
5355

56+
// Capture the current cursor position and visible ranges if the file is open
57+
const activeEditor = vscode.window.activeTextEditor
58+
if (activeEditor && arePathsEqual(activeEditor.document.uri.fsPath, absolutePath)) {
59+
this.savedCursorPosition = activeEditor.selection.active
60+
this.savedVisibleRanges = [...activeEditor.visibleRanges] // Create a copy of the readonly array
61+
}
62+
5463
// If the file is already open, ensure it's not dirty before getting its
5564
// contents.
5665
if (fileExists) {
@@ -207,7 +216,29 @@ export class DiffViewProvider {
207216
await updatedDocument.save()
208217
}
209218

210-
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { preview: false, preserveFocus: true })
219+
// Show the document and restore cursor position
220+
const editor = await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
221+
preview: false,
222+
preserveFocus: true,
223+
})
224+
225+
// Restore the saved cursor position and visible range
226+
if (this.savedCursorPosition) {
227+
const newPosition = this.savedCursorPosition
228+
editor.selection = new vscode.Selection(newPosition, newPosition)
229+
230+
// Restore the visible range if it was saved
231+
if (this.savedVisibleRanges && this.savedVisibleRanges.length > 0) {
232+
editor.revealRange(this.savedVisibleRanges[0], vscode.TextEditorRevealType.Default)
233+
} else {
234+
// If no visible range was saved, at least reveal the cursor position
235+
editor.revealRange(
236+
new vscode.Range(newPosition, newPosition),
237+
vscode.TextEditorRevealType.InCenterIfOutsideViewport,
238+
)
239+
}
240+
}
241+
211242
await this.closeAllDiffViews()
212243

213244
// Getting diagnostics before and after the file edit is a better approach than
@@ -405,10 +436,23 @@ export class DiffViewProvider {
405436
await updatedDocument.save()
406437

407438
if (this.documentWasOpen) {
408-
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
439+
const editor = await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
409440
preview: false,
410441
preserveFocus: true,
411442
})
443+
444+
// Restore cursor position after reverting
445+
if (this.savedCursorPosition) {
446+
editor.selection = new vscode.Selection(this.savedCursorPosition, this.savedCursorPosition)
447+
if (this.savedVisibleRanges && this.savedVisibleRanges.length > 0) {
448+
editor.revealRange(this.savedVisibleRanges[0], vscode.TextEditorRevealType.Default)
449+
} else {
450+
editor.revealRange(
451+
new vscode.Range(this.savedCursorPosition, this.savedCursorPosition),
452+
vscode.TextEditorRevealType.InCenterIfOutsideViewport,
453+
)
454+
}
455+
}
412456
}
413457

414458
await this.closeAllDiffViews()
@@ -627,6 +671,8 @@ export class DiffViewProvider {
627671
this.activeLineController = undefined
628672
this.streamedLines = []
629673
this.preDiagnostics = []
674+
this.savedCursorPosition = undefined
675+
this.savedVisibleRanges = undefined
630676
}
631677

632678
/**
@@ -658,14 +704,36 @@ export class DiffViewProvider {
658704
await createDirectoriesForFile(absolutePath)
659705
await fs.writeFile(absolutePath, content, "utf-8")
660706

707+
// Capture the current cursor position and visible ranges before any file operations
708+
const activeEditor = vscode.window.activeTextEditor
709+
let savedPosition: vscode.Position | undefined
710+
let savedRanges: vscode.Range[] | undefined
711+
if (activeEditor && arePathsEqual(activeEditor.document.uri.fsPath, absolutePath)) {
712+
savedPosition = activeEditor.selection.active
713+
savedRanges = [...activeEditor.visibleRanges] // Create a copy of the readonly array
714+
}
715+
661716
// Open the document to ensure diagnostics are loaded
662717
// When openFile is false (PREVENT_FOCUS_DISRUPTION enabled), we only open in memory
663718
if (openFile) {
664719
// Show the document in the editor
665-
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
720+
const editor = await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
666721
preview: false,
667722
preserveFocus: true,
668723
})
724+
725+
// Restore cursor position if we had one saved
726+
if (savedPosition) {
727+
editor.selection = new vscode.Selection(savedPosition, savedPosition)
728+
if (savedRanges && savedRanges.length > 0) {
729+
editor.revealRange(savedRanges[0], vscode.TextEditorRevealType.Default)
730+
} else {
731+
editor.revealRange(
732+
new vscode.Range(savedPosition, savedPosition),
733+
vscode.TextEditorRevealType.InCenterIfOutsideViewport,
734+
)
735+
}
736+
}
669737
} else {
670738
// Just open the document in memory to trigger diagnostics without showing it
671739
const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(absolutePath))

0 commit comments

Comments
 (0)