Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 71 additions & 3 deletions src/integrations/editor/DiffViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Copy link
Contributor Author

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(), and saveDirectly(). Could we extract this into a private helper method like:

private restoreCursorPosition(editor: vscode.TextEditor): void {
  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
      );
    }
  }
}

This would reduce duplication and make future maintenance easier.

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)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice we're using TextEditorRevealType.Default here for saved ranges, but InCenterIfOutsideViewport when no saved range exists (line 237). The same pattern appears in revertChanges() and saveDirectly(). Would it be better to use InCenterIfOutsideViewport consistently to ensure the cursor is always visible to the user?

} 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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -627,6 +671,8 @@ export class DiffViewProvider {
this.activeLineController = undefined
this.streamedLines = []
this.preDiagnostics = []
this.savedCursorPosition = undefined
this.savedVisibleRanges = undefined
}

/**
Expand Down Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 fs.writeFile call to ensure we always get the correct position.

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))
Expand Down
Loading