-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix: restore cursor position after applying diffs #6855
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,8 @@ export class DiffViewProvider { | |
| private streamedLines: string[] = [] | ||
| private preDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = [] | ||
| private taskRef: WeakRef<Task> | ||
| private savedCursorPosition?: vscode.Position | ||
| private savedVisibleRanges?: vscode.Range[] | ||
|
|
||
| constructor( | ||
| private cwd: string, | ||
|
|
@@ -51,6 +53,13 @@ export class DiffViewProvider { | |
| const absolutePath = path.resolve(this.cwd, relPath) | ||
| this.isEditing = true | ||
|
|
||
| // Capture the current cursor position and visible ranges if the file is open | ||
| const activeEditor = vscode.window.activeTextEditor | ||
| if (activeEditor && arePathsEqual(activeEditor.document.uri.fsPath, absolutePath)) { | ||
| this.savedCursorPosition = activeEditor.selection.active | ||
| this.savedVisibleRanges = [...activeEditor.visibleRanges] // Create a copy of the readonly array | ||
| } | ||
|
|
||
| // If the file is already open, ensure it's not dirty before getting its | ||
| // contents. | ||
| if (fileExists) { | ||
|
|
@@ -207,7 +216,29 @@ export class DiffViewProvider { | |
| await updatedDocument.save() | ||
| } | ||
|
|
||
| await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { preview: false, preserveFocus: true }) | ||
| // Show the document and restore cursor position | ||
| const editor = await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { | ||
| preview: false, | ||
| preserveFocus: true, | ||
| }) | ||
|
|
||
| // Restore the saved cursor position and visible range | ||
| if (this.savedCursorPosition) { | ||
| const newPosition = this.savedCursorPosition | ||
| editor.selection = new vscode.Selection(newPosition, newPosition) | ||
|
|
||
| // Restore the visible range if it was saved | ||
| if (this.savedVisibleRanges && this.savedVisibleRanges.length > 0) { | ||
| editor.revealRange(this.savedVisibleRanges[0], vscode.TextEditorRevealType.Default) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice we're using |
||
| } else { | ||
| // If no visible range was saved, at least reveal the cursor position | ||
| editor.revealRange( | ||
| new vscode.Range(newPosition, newPosition), | ||
| vscode.TextEditorRevealType.InCenterIfOutsideViewport, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| await this.closeAllDiffViews() | ||
|
|
||
| // Getting diagnostics before and after the file edit is a better approach than | ||
|
|
@@ -405,10 +436,23 @@ export class DiffViewProvider { | |
| await updatedDocument.save() | ||
|
|
||
| if (this.documentWasOpen) { | ||
| await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { | ||
| const editor = await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { | ||
| preview: false, | ||
| preserveFocus: true, | ||
| }) | ||
|
|
||
| // Restore cursor position after reverting | ||
| if (this.savedCursorPosition) { | ||
| editor.selection = new vscode.Selection(this.savedCursorPosition, this.savedCursorPosition) | ||
| if (this.savedVisibleRanges && this.savedVisibleRanges.length > 0) { | ||
| editor.revealRange(this.savedVisibleRanges[0], vscode.TextEditorRevealType.Default) | ||
| } else { | ||
| editor.revealRange( | ||
| new vscode.Range(this.savedCursorPosition, this.savedCursorPosition), | ||
| vscode.TextEditorRevealType.InCenterIfOutsideViewport, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| await this.closeAllDiffViews() | ||
|
|
@@ -627,6 +671,8 @@ export class DiffViewProvider { | |
| this.activeLineController = undefined | ||
| this.streamedLines = [] | ||
| this.preDiagnostics = [] | ||
| this.savedCursorPosition = undefined | ||
| this.savedVisibleRanges = undefined | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -658,14 +704,36 @@ export class DiffViewProvider { | |
| await createDirectoriesForFile(absolutePath) | ||
| await fs.writeFile(absolutePath, content, "utf-8") | ||
|
|
||
| // Capture the current cursor position and visible ranges before any file operations | ||
| const activeEditor = vscode.window.activeTextEditor | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this intentional? The cursor position is captured AFTER writing the file (line 705). If the file write triggers an automatic reload in VSCode, we might miss the original cursor position. Consider moving this capture block before the |
||
| let savedPosition: vscode.Position | undefined | ||
| let savedRanges: vscode.Range[] | undefined | ||
| if (activeEditor && arePathsEqual(activeEditor.document.uri.fsPath, absolutePath)) { | ||
| savedPosition = activeEditor.selection.active | ||
| savedRanges = [...activeEditor.visibleRanges] // Create a copy of the readonly array | ||
| } | ||
|
|
||
| // Open the document to ensure diagnostics are loaded | ||
| // When openFile is false (PREVENT_FOCUS_DISRUPTION enabled), we only open in memory | ||
| if (openFile) { | ||
| // Show the document in the editor | ||
| await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { | ||
| const editor = await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { | ||
| preview: false, | ||
| preserveFocus: true, | ||
| }) | ||
|
|
||
| // Restore cursor position if we had one saved | ||
| if (savedPosition) { | ||
| editor.selection = new vscode.Selection(savedPosition, savedPosition) | ||
| if (savedRanges && savedRanges.length > 0) { | ||
| editor.revealRange(savedRanges[0], vscode.TextEditorRevealType.Default) | ||
| } else { | ||
| editor.revealRange( | ||
| new vscode.Range(savedPosition, savedPosition), | ||
| vscode.TextEditorRevealType.InCenterIfOutsideViewport, | ||
| ) | ||
| } | ||
| } | ||
| } else { | ||
| // Just open the document in memory to trigger diagnostics without showing it | ||
| const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(absolutePath)) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cursor restoration logic is duplicated across
saveChanges(),revertChanges(), andsaveDirectly(). Could we extract this into a private helper method like:This would reduce duplication and make future maintenance easier.