Browse Source

Fix: Preserve editor state and prevent tab unpinning during diffs (#2857)

- Maintains editor view column state when closing and reopening files during diff operations, ensuring tabs stay opened in their original position.

- Prevents closing the original editor tab when opening the diff view, preserving pinned status when applying changes via write_to_file or apply_diff.

- Updates VSCode workspace launch flag from -n to -W for compatibility.
seedlord 10 months ago
parent
commit
c2dd743aeb
2 changed files with 61 additions and 10 deletions
  1. 1 1
      evals/apps/cli/src/index.ts
  2. 60 9
      src/integrations/editor/DiffViewProvider.ts

+ 1 - 1
evals/apps/cli/src/index.ts

@@ -190,7 +190,7 @@ const runExercise = async ({ run, task, server }: { run: Run; task: Task; server
 			ROO_CODE_IPC_SOCKET_PATH: taskSocketPath,
 		},
 		shell: "/bin/bash",
-	})`code --disable-workspace-trust -n ${workspacePath}`
+	})`code --disable-workspace-trust -W ${workspacePath}`
 
 	// Give VSCode some time to spawn before connecting to its unix socket.
 	await new Promise((resolve) => setTimeout(resolve, 3_000))

+ 60 - 9
src/integrations/editor/DiffViewProvider.ts

@@ -17,6 +17,7 @@ export class DiffViewProvider {
 	originalContent: string | undefined
 	private createdDirs: string[] = []
 	private documentWasOpen = false
+	private originalViewColumn?: vscode.ViewColumn // Store the original view column
 	private relPath?: string
 	private newContent?: string
 	private activeDiffEditor?: vscode.TextEditor
@@ -65,11 +66,22 @@ export class DiffViewProvider {
 			.filter(
 				(tab) => tab.input instanceof vscode.TabInputText && arePathsEqual(tab.input.uri.fsPath, absolutePath),
 			)
+		// Check if the document is already open and store its state
+		// DO NOT close the original tab to preserve pin status
 		for (const tab of tabs) {
-			if (!tab.isDirty) {
-				await vscode.window.tabGroups.close(tab)
+			if (tab.input instanceof vscode.TabInputText && arePathsEqual(tab.input.uri.fsPath, absolutePath)) {
+				this.originalViewColumn = tab.group.viewColumn
+				this.documentWasOpen = true
+				// Ensure the tab is not dirty before proceeding, but don't close it
+				if (tab.isDirty) {
+					// Find the document associated with the tab and save it
+					const doc = vscode.workspace.textDocuments.find((d) => arePathsEqual(d.uri.fsPath, absolutePath))
+					if (doc) {
+						await doc.save()
+					}
+				}
+				break // Found the relevant tab, no need to check others
 			}
-			this.documentWasOpen = true
 		}
 		this.activeDiffEditor = await this.openDiffEditor()
 		this.fadedOverlayController = new DecorationController("fadedOverlay", this.activeDiffEditor)
@@ -156,9 +168,31 @@ export class DiffViewProvider {
 			await updatedDocument.save()
 		}
 
-		await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { preview: false })
+		// Close the diff view first
 		await this.closeAllDiffViews()
 
+		// If the original document was open, try to focus it.
+		// VS Code should handle showing the updated content automatically since the file was saved.
+		if (this.documentWasOpen && this.originalViewColumn) {
+			// Find the editor for the original document and reveal it
+			const originalEditor = vscode.window.visibleTextEditors.find(
+				(editor) =>
+					arePathsEqual(editor.document.uri.fsPath, absolutePath) &&
+					editor.viewColumn === this.originalViewColumn,
+			)
+			if (originalEditor) {
+				// Reveal a range (e.g., the start) to ensure focus
+				const position = new vscode.Position(0, 0)
+				originalEditor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.AtTop)
+			} else {
+				// Fallback if editor not found (shouldn't happen often if documentWasOpen is true)
+				await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
+					preview: false,
+					viewColumn: this.originalViewColumn,
+				})
+			}
+		}
+
 		/*
 		Getting diagnostics before and after the file edit is a better approach than
 		automatically tracking problems in real-time. This method ensures we only
@@ -237,12 +271,28 @@ export class DiffViewProvider {
 			await vscode.workspace.applyEdit(edit)
 			await updatedDocument.save()
 			console.log(`File ${absolutePath} has been reverted to its original content.`)
-			if (this.documentWasOpen) {
-				await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
-					preview: false,
-				})
-			}
+			// Close the diff view first
 			await this.closeAllDiffViews()
+
+			// If the document was originally open, ensure it's focused.
+			// The revert logic already applied the original content and saved.
+			if (this.documentWasOpen && this.originalViewColumn) {
+				const originalEditor = vscode.window.visibleTextEditors.find(
+					(editor) =>
+						arePathsEqual(editor.document.uri.fsPath, absolutePath) &&
+						editor.viewColumn === this.originalViewColumn,
+				)
+				if (originalEditor) {
+					const position = new vscode.Position(0, 0)
+					originalEditor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.AtTop)
+				} else {
+					// Fallback
+					await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
+						preview: false,
+						viewColumn: this.originalViewColumn,
+					})
+				}
+			}
 		}
 
 		// edit is done
@@ -358,6 +408,7 @@ export class DiffViewProvider {
 		this.originalContent = undefined
 		this.createdDirs = []
 		this.documentWasOpen = false
+		this.originalViewColumn = undefined // Reset stored view column
 		this.activeDiffEditor = undefined
 		this.fadedOverlayController = undefined
 		this.activeLineController = undefined