Skip to content

Conversation

@felixAnhalt
Copy link

@felixAnhalt felixAnhalt commented Apr 25, 2025

Context

I added an editable setting to allow users to preserve focus on the tab they are in while roo code is opening new tabs to do what it has to do.
Fixes #2122.

Implementation

Added roo-cline.diffViewAutoFocus in the VSCode settings.json as well as all the attributes and types related to that.
Added message stuff for frontend and backend communication. Adjuste behavior of DiffCheckViewer to preserve editor focus or don't, depending on the setting set. Left this option with default true for an opt-out experience, so that the previous behavior is suststained if one doesn't excplicitely wants to change it.
Added lots of settings to control editing behavior.
New Settings Page:

  • Option to use diffs to edit files
  • Option to just write with the file system

If diff editing is enabled:

  • Option to close newly created and previously not opened roo tabs

  • Option to close all tabs roo touched

  • Option to focus the diff view

  • Option to open the diff view in the correct window

  • Option to open the tabs at the end of the tab list

Screenshots

New Settings Page

image

Auto Focus Enabled

auto_focus_enabled.mov

Auto Focus Disabled

auto_focus_disabled.mov

Auto Closing of Tabs

auto_close.1.mov

Standard behavior: 00:00 - 00:18
Close All Opened Tabs with example tab already open (shouldn't be closed): 00:29 - 00:45
Close All Opened Tabs w/o example tab opened (both should be closed): 05:02 - 05:07 (quite fast!)

How to Test

Follow the steps from the video.
En- disable the setting once.
Execute a with- and without it enabled to verify that it steals focus when autoFocus is enabed and doesn't if not.

Get in Touch

Discord handle: icy_ice_pls

Anyways, here's GitHubs automatic summary:

This pull request introduces several changes to enhance the functionality of the Roo Code editor, including the addition of new settings, the replacement of the DiffViewProvider with a more versatile EditingProvider, and the removal of legacy migration logic for diff settings. The updates aim to improve user experience by providing more customization options and streamlining the codebase.

New Features and Settings:

  • Added an editable setting to preserve focus on the current tab while Roo Code opens new tabs (.changeset/large-snakes-suffer.md).
  • Introduced new global settings such as diffViewAutoFocus, autoCloseRooTabs, and openTabsAtEndOfList in globalSettingsSchema (packages/types/src/global-settings.ts).

Migration and Cleanup:

  • Removed obsolete diffSettingsMigrated logic and the migrateDiffSettings method from ProviderSettingsManager (src/core/config/ProviderSettingsManager.ts). [1] [2]
  • Deleted diffEnabled and fuzzyMatchThreshold from baseProviderSettingsSchema as they are no longer required (packages/types/src/provider-settings.ts).

Refactoring for Editing Provider:

  • Replaced DiffViewProvider with IEditingProvider throughout the Task class, enabling more flexible editing operations (src/core/task/Task.ts). [1] [2]
  • Updated methods in Task to use EditingProviderFactory for creating and resetting editing providers (src/core/task/Task.ts). [1] [2]

Test Updates:

  • Updated tests to reflect the replacement of diffViewProvider with editingProvider in mock objects and assertions (src/core/tools/__tests__/writeToFileTool.spec.ts). [1] [2]

These changes collectively improve the extensibility and maintainability of the Roo Code editor while enhancing the user experience.


Important

This PR adds new settings to manage editor focus and tab behavior in Roo Code, refactors editing providers, and updates the UI and tests accordingly.

  • Behavior:
    • Adds roo-cline.diffViewAutoFocus setting to control editor focus behavior when opening new tabs.
    • Introduces settings for auto-closing Roo tabs and opening tabs at the end of the list.
    • Default behavior is to focus on new tabs unless settings are changed.
  • Settings and Configuration:
    • Adds new settings to settings.json for diffViewAutoFocus, autoCloseRooTabs, openTabsAtEndOfList, and more.
    • Updates globalSettingsSchema in global-settings.ts to include new settings.
  • Refactoring and Implementation:
    • Replaces DiffViewProvider with IEditingProvider in Task.ts for more flexible editing operations.
    • Introduces EditingProviderFactory to create appropriate editing providers based on settings.
    • Removes legacy diffSettingsMigrated logic from ProviderSettingsManager.ts.
  • UI and Frontend:
    • Adds FileEditingOptions component for new settings in the UI.
    • Updates SettingsView.tsx to include new file editing options.
  • Testing:
    • Updates tests to reflect changes in editing provider logic and new settings.
    • Adds tests for EditingProviderFactory, FileWriter, and UserInteractionProvider.

This description was created by Ellipsis for b4f213e. You can customize this summary. It will automatically update as commits are pushed.

@changeset-bot
Copy link

changeset-bot bot commented Apr 25, 2025

🦋 Changeset detected

Latest commit: c3e4794

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
roo-cline Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@felixAnhalt felixAnhalt marked this pull request as ready for review April 25, 2025 20:36
@felixAnhalt felixAnhalt requested review from cte and mrubens as code owners April 25, 2025 20:36
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request labels Apr 25, 2025
@seedlord seedlord mentioned this pull request Apr 25, 2025
@seedlord
Copy link
Contributor

thanks for that awesome PR.
I tried something similar #2908

@KJ7LNW
Copy link
Contributor

KJ7LNW commented Apr 25, 2025

awesome! Does it work if you tear off a roo tab by clicking
image
and then dragging into a new window?

@felixAnhalt
Copy link
Author

awesome! Does it work if you tear off a roo tab by clicking image and then dragging into a new window?

@KJ7LNW
Yes, looks like it.
Actually did not think about that beforehand, but it is possible to have different windows open doing different things with this set up. This seems to be quite nice for A2A use cases if thought broader. Maybe the architect could send out multiple coders to do their thing? I don't know, just thinking out loud right now.
Anyways, the example:

Screen.Recording.2025-04-26.at.11.58.41.1.mov

@felixAnhalt felixAnhalt force-pushed the feature/2122-editor-focus branch from 627e4af to 7a4e964 Compare April 26, 2025 10:24
@seedlord
Copy link
Contributor

If you have multiple files in a single window/group, will edits by roo keep the tab position in the tabbar?

@felixAnhalt
Copy link
Author

If you have multiple files in a single window/group, will edits by roo keep the tab position in the tabbar?

I just set up multiple windows with multiple tabs and let it go for it.
Interestingly, roo closes the tab even if the file was opened before.
Otherwise, nothing exciting is happening.
Something mundane though: when roo starts in a new diff, it forces an enter upon my input as you can see in the vid at 0:05 till 0:07.
Anyways, here you can watch how it behaves.

Screen.Recording.2025-04-26.at.22.11.43.mov

@KJ7LNW
Copy link
Contributor

KJ7LNW commented Apr 27, 2025

Interestingly, roo closes the tab even if the file was opened before.

I noticed that too.

I am running your PR in my daily driver, and it really works great.

Also noticed:

  1. Open a file
    image

  2. click image and it opens "Working Tree" if it is in git:
    image

  3. Have Roo edit the same file, and then notice it does not retain the correct tab. After edit, it jumps to the original not working-tree:
    image

@KJ7LNW
Copy link
Contributor

KJ7LNW commented Apr 27, 2025

I've been editing in multiple Roo windows (same vscode instance/repo) and the editor window seems to pop up in unexpected locations.

Could you see if viewColumn: vscode.ViewColumn.Active will keep new editor pop-ups in the correct window?

An this case "Auto-approve Write" was disabled because I needed to approve any changes before letting it go, but I wanted it to open in the relevant task window. instead I think it opened in whatever window had focus.

@felixAnhalt
Copy link
Author

hey @KJ7LNW
It seems that this happens because of this part here and it seems to be intended behavior. I don't know what the releated issues leading to this behavior was, but it seems to be intentional.
Does it make sense to disable this behavior if we are in non-autofocus mode from a product perspective?
I'd be happy to add that.

@felixAnhalt
Copy link
Author

viewColumn: vscode.ViewColumn.Active doesn't help here.
It then opens the tabs in the roo code window first used to start a task.
I can have a look into that this evening my time.

@seedlord
Copy link
Contributor

I tried to make tabs stay opened and make the diffview popup next to the original tab location. Works across groups, and for pinned tabs too (so that they dont get unpinned and stay in their original position), but that broke the "problems" detection for roo somehow. Maybe you can implement it?
#2857

@felixAnhalt
Copy link
Author

felixAnhalt commented Apr 27, 2025

hey @seedlord I had a look at that.
Looks nice, but doesn't help in this current case.
My current understanding is that the problem is that in this part the viewColumn is set wrongly. This happens before originalViewColumn is set (or at least it's still undefined in the debugger).
I have provided an exemplary implementation on this branch.

Therefore I assume we either need to find the correct viewColumn by finding out which group was responsible for the current call or find the current webView via some shenaningans with the context.
I have seen that openClineInNewTab accessess some kind of context and returns a tabgroup. I don't know if that's helpful.
Assistance with finding the correct viewColumn of the currently responsible editor group would be appreciated :)

@hannesrudolph hannesrudolph moved this from New to PR [Pre Approval Review] in Roo Code Roadmap Apr 28, 2025
@KJ7LNW
Copy link
Contributor

KJ7LNW commented Apr 28, 2025

hey @KJ7LNW It seems that this happens because of this part here and it seems to be intended behavior. I don't know what the releated issues leading to this behavior was, but it seems to be intentional. Does it make sense to disable this behavior if we are in non-autofocus mode from a product perspective? I'd be happy to add that.

  1. I think so, if we are not focusing, then we should try not to interrupt the user in any way.
  2. related to interrupting the user: I have also noticed that when windows open automatically to edit files, it will create a new tab group column, which is particularly distracting if I have a side-by-side view open because it squashes the view substantially. If possible, it would be nice for that new edit tab to appear in the same tab group where I am already working but without pulling focus so it adds a tab to the top but does not change the view in any way.
  3. It could also be a good idea for the user to be interrupted if !autoApprove(write) so that the user knows it is waiting for them.

Some of this will depend on what VS Code actually supports, but the following could be a useful consideration:

  1. if Roo is the first instance running from the sidebar: open the edit window in the same tab group that is already active but without changing focus (it would show up as a tab but stay in the background and not be selected)
  2. if Roo is not the first instance (ie, running from a tab in a different window): open edit files in the same tab group so it this place in that same torn off window. (I believe that if the Roo tab group is locked it would open in that same window but in a new tab groups column so that it does not interrupt view of Roo, sort of emulating a sidebar in that second window.)

@felixAnhalt
Copy link
Author

Hey
For now I found out how to reliably find the correct viewColumn by doing the following:

// applyDiffTool.ts
const clineRef = cline.providerRef.deref()
const viewColumn = clineRef?.getViewColumn() ?? ViewColumn.Beside

// ClineProvider.ts
public getViewColumn(): vscode.ViewColumn {
  const isViewPanel = this.view?.viewType === "roo-cline.TabPanelProvider"
  if (!isViewPanel) {
	  return vscode.ViewColumn.Beside
  }
  // If the view is a WebviewPanel, return its viewColumn.
  // This property is only set if the webview is in one of the editor view columns.
  // Therefore, we can safely return it or default to beside.
  return (this.view as vscode.WebviewPanel).viewColumn ?? vscode.ViewColumn.Beside
}

Regarding the user disruption:
I think here we may run into problems with how vscode (specifically the vscode.diff command) works.
The documentation for vscode.diff only gives us the TextDocumentsShowOptions and there are not really any configurations we can apply for the tab to be opened in the background.

I'm not aware of other options to use some kind of "open in new tab" behavior known from browsers for example.
What do you think?

@KJ7LNW
Copy link
Contributor

KJ7LNW commented Apr 30, 2025

I'm not aware of other options to use some kind of "open in new tab" behavior known from browsers for example.

you might be hitting the limitations of the vs code API. you could try this:

I have done this many times successfully for things like shell integration. VScode is a big project and Roo has to read a bunch of files for a while to find out what you're looking for, but it does a pretty good job.

@felixAnhalt
Copy link
Author

felixAnhalt commented May 1, 2025

That was a lot of fun.
Didn't find a straight-forward solution though.
What I found was the following:

  • VSCode registers the .diff command here.
  • First I had a look at the typeConverters.TextEditorOpenOptions which are defined here.
  • They expose backgound and override. I tried those and it didn't affect the behavior.
  • Then I looked into what actually happens when calling vscode.diff, the implementation can be found here.
  • This calls editorService.openEditor which in turn accepts an options object.
  • The editorService.openEditor method uses this options object with this type.
  • Therefore I tried the following configuration:
    const textDocumentShowOptions: IEditorOptions = {
      preview: false,
      preserveFocus: !autoFocus,
      viewColumn: viewColumn ?? ViewColumn.Beside,
      inactive: !autoFocus,
      revealIfVisible: false,
      revealIfOpened: false,
      transient: true,
      pinned: false,
    }
  • This didn't affect the behavior as well.

Eventually I settled with temporarily saving a reference to vscode.window.activeTextEditor and then showing that one again after the promise is resolved.

Furthermore:

  1. related to interrupting the user: I have also noticed that when windows open automatically to edit files, it will create a new tab group column, which is particularly distracting if I have a side-by-side view open because it squashes the view substantially. If possible, it would be nice for that new edit tab to appear in the same tab group where I am already working but without pulling focus so it adds a tab to the top but does not change the view in any way.

I tried to open it in the same tab group and that definitively steals focus.
I think there's not really a way getting around that.
Right now the file we open to edit also remains inside the new tab group in case of disabled auto focus after calling closeAllDiffViews, which is a problem, I think.
I would propose to close all newly opened tabs instead of just the diffView inside closeAllDiffViews (and renaming that obv).
Maybe even being indifferent about auto focus here and generally just tracking which of the tabs we use were newly created and which are tab groups we created.
What do you think?

@KJ7LNW
Copy link
Contributor

KJ7LNW commented May 1, 2025

I tried to open it in the same tab group and that definitively steals focus.
I think there's not really a way getting around that.

When I was testing (in a branch that I never created a pr for) I was able to open in the same tag group without stealing focus, and most of the time it even opened that tab in the window where Roo was, which seemed empirically to be caused by vscode.ViewColumn.Active ... however you said that did not work for you, so maybe it is because I am running an "insiders" build, or maybe it does work under certain circumstances like which window is the selected foreground window?

The entire diff is below, but I think this is the relevant part that got me close to that goal:

+		await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
+			preview: false,
+			viewColumn: vscode.ViewColumn.Active,
+			preserveFocus: true,
+		})

Right now the file we open to edit also remains inside the new tab group in case of disabled auto focus after calling closeAllDiffViews, which is a problem, I think.

I agree with you: it should open in the same existing tab group without stealing focus, unless:

  1. The feature is turned off, or
  2. "Auto-approve writes" is turned off, because then I want it to pop-up in front of me

I would propose to close all newly opened tabs instead of just the diffView inside closeAllDiffViews (and renaming that obv).

There are times when i really wish it would leave the split-diff window open ("Working Tree") after editing so I can review while it works on something else, but I know the number of tabs can also become too much clutter. I am sure there are cases when users want it one way or the other (indeed, I want it one way or the other depending on what type of work I am doing).

So, this might be a useful configuration option: "close tabs after editing unless they were already open"

critical: "unless they were already open" - sometimes windows closed and I was looking at something and I really wish it would not surprise me.

Relatedly, there seems to be a behavior where existing diff windows are closed after editing, which I think you correctly pointed out as a problem with closeAllDiffViews.

Maybe even being indifferent about auto focus here and generally just tracking which of the tabs we use were newly > created and which are tab groups we created.
What do you think?

To reiterate above: Intelligent use of auto-focus is a prime goal of this PR: it should open somewhere sane* without stealing focus, unless:

  1. The feature is turned off, or
  2. "Auto-approve writes" is turned off, because then I want it to pop-up in front of me

Where "sane" means that it does not steal my input, nor does it affect the view of the file I am currently looking at. Examples of "sane" in this case might mean:

  • "in the same existing tab group, but without switching tabs" or
  • "in the torn off window with another Roo tab that is working on something while I look at the main vs code editing window (because I do not care what happens in that other window as long as it does not interrupt me in the main window)"
  • others?

Here is the entire diff that I worked on in case it is useful for reference:

My old testing commits

First mostly working commit

commit b009fb71cd7da428780b186edd347ed7d0290b64
Author: Eric Wheeler
Date:   Fri Apr 11 16:10:34 2025 -0700

    feat: improve diff view focus handling
    
    Add preserveFocus and viewColumn options to diff view operations
    Switch to onDidChangeVisibleTextEditors for better editor tracking

diff --git a/src/integrations/editor/DiffViewProvider.ts b/src/integrations/editor/DiffViewProvider.ts
index 0bf49485..412d275a 100644
--- a/src/integrations/editor/DiffViewProvider.ts
+++ b/src/integrations/editor/DiffViewProvider.ts
@@ -156,9 +156,20 @@ export class DiffViewProvider {
 			await updatedDocument.save()
 		}
 
-		await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), { preview: false })
-		await this.closeAllDiffViews()
+		const currentEditor = vscode.window.activeTextEditor
+		await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
+			preview: false,
+			viewColumn: vscode.ViewColumn.Active,
+			preserveFocus: true,
+		})
+		if (currentEditor) {
+			await vscode.window.showTextDocument(currentEditor.document, {
+				viewColumn: currentEditor.viewColumn,
+				selection: currentEditor.selection,
+			})
+		}
 
+		await this.closeAllDiffViews()
 		/*
 		Getting diagnostics before and after the file edit is a better approach than
 		automatically tracking problems in real-time. This method ensures we only
@@ -280,15 +291,26 @@ export class DiffViewProvider {
 					arePathsEqual(tab.input.modified.fsPath, uri.fsPath),
 			)
 		if (diffTab && diffTab.input instanceof vscode.TabInputTextDiff) {
-			const editor = await vscode.window.showTextDocument(diffTab.input.modified)
+			const currentEditor = vscode.window.activeTextEditor
+			const editor = await vscode.window.showTextDocument(diffTab.input.modified, {
+				viewColumn: vscode.ViewColumn.Active,
+				preserveFocus: true,
+			})
+			if (currentEditor) {
+				await vscode.window.showTextDocument(currentEditor.document, {
+					viewColumn: currentEditor.viewColumn,
+					selection: currentEditor.selection,
+				})
+			}
 			return editor
 		}
 		// Open new diff editor
 		return new Promise<vscode.TextEditor>((resolve, reject) => {
 			const fileName = path.basename(uri.fsPath)
 			const fileExists = this.editType === "modify"
-			const disposable = vscode.window.onDidChangeActiveTextEditor((editor) => {
-				if (editor && arePathsEqual(editor.document.uri.fsPath, uri.fsPath)) {
+			const disposable = vscode.window.onDidChangeVisibleTextEditors((editors) => {
+				const editor = editors.find((e) => arePathsEqual(e.document.uri.fsPath, uri.fsPath))
+				if (editor) {
 					disposable.dispose()
 					resolve(editor)
 				}
@@ -300,6 +322,7 @@ export class DiffViewProvider {
 				}),
 				uri,
 				`${fileName}: ${fileExists ? "Original ↔ Roo's Changes" : "New File"} (Editable)`,
+				{ preserveFocus: true, viewColumn: vscode.ViewColumn.Active },
 			)
 			// This may happen on very slow machines ie project idx
 			setTimeout(() => {

Second WIP commit

commit 7700b2fe44e64e8e8f0b79a18f3f0136ade99c53
Author: Eric Wheeler
Date:   Fri Apr 25 20:02:02 2025 -0700

    not working the way I want yet, needs further testing and troubleshooting

diff --git a/src/integrations/editor/DiffViewProvider.ts b/src/integrations/editor/DiffViewProvider.ts
index 412d275a..958ccb5b 100644
--- a/src/integrations/editor/DiffViewProvider.ts
+++ b/src/integrations/editor/DiffViewProvider.ts
@@ -8,6 +8,7 @@ import { DecorationController } from "./DecorationController"
 import * as diff from "diff"
 import { diagnosticsToProblemsString, getNewDiagnostics } from "../diagnostics"
 import stripBom from "strip-bom"
+import { ClineProvider } from "../../core/webview/ClineProvider"
 
 export const DIFF_VIEW_URI_SCHEME = "cline-diff"
 
@@ -20,6 +21,7 @@ export class DiffViewProvider {
 	private relPath?: string
 	private newContent?: string
 	private activeDiffEditor?: vscode.TextEditor
+	private savedEditor?: { editor: vscode.TextEditor; selection: vscode.Selection }
 	private fadedOverlayController?: DecorationController
 	private activeLineController?: DecorationController
 	private streamedLines: string[] = []
@@ -156,17 +158,18 @@ export class DiffViewProvider {
 			await updatedDocument.save()
 		}
 
-		const currentEditor = vscode.window.activeTextEditor
 		await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
 			preview: false,
 			viewColumn: vscode.ViewColumn.Active,
 			preserveFocus: true,
 		})
-		if (currentEditor) {
-			await vscode.window.showTextDocument(currentEditor.document, {
-				viewColumn: currentEditor.viewColumn,
-				selection: currentEditor.selection,
+		// Restore the editor that was active when diff was opened
+		if (this.savedEditor) {
+			await vscode.window.showTextDocument(this.savedEditor.editor.document, {
+				selection: this.savedEditor.selection,
 			})
+			// Clear saved editor after restoring
+			this.savedEditor = undefined
 		}
 
 		await this.closeAllDiffViews()
@@ -280,6 +283,15 @@ export class DiffViewProvider {
 		if (!this.relPath) {
 			throw new Error("No file path set")
 		}
+		const provider = ClineProvider.getVisibleInstance()
+		const preserveFocus = provider?.getValue("autoApprovalEnabled") && provider?.getValue("alwaysAllowWrite")
+		// Store current editor before opening diff
+		if (vscode.window.activeTextEditor) {
+			this.savedEditor = {
+				editor: vscode.window.activeTextEditor,
+				selection: vscode.window.activeTextEditor.selection,
+			}
+		}
 		const uri = vscode.Uri.file(path.resolve(this.cwd, this.relPath))
 		// If this diff editor is already open (ie if a previous write file was interrupted) then we should activate that instead of opening a new diff
 		const diffTab = vscode.window.tabGroups.all
@@ -294,11 +306,10 @@ export class DiffViewProvider {
 			const currentEditor = vscode.window.activeTextEditor
 			const editor = await vscode.window.showTextDocument(diffTab.input.modified, {
 				viewColumn: vscode.ViewColumn.Active,
-				preserveFocus: true,
+				preserveFocus,
 			})
 			if (currentEditor) {
 				await vscode.window.showTextDocument(currentEditor.document, {
-					viewColumn: currentEditor.viewColumn,
 					selection: currentEditor.selection,
 				})
 			}

@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels May 2, 2025
@felixAnhalt
Copy link
Author

felixAnhalt commented May 2, 2025

I added the functionality to

close tabs after editing unless they were already open
here by using a variable to save all newly created tabs.
I did not add a setting for roo which allows for this to be configured.
Do you think the adjustment of this behavior still belongs into the scope of this PR or rather into a new issue?

I also added the checks for Auto-approve here.

Anyways, regarding the focus preservation:

I did not get it working that the tab is opened in the background inside the active tab group.
It opens there, but there are a couple of ms where you can break things by typing fast.
Using selection to get the cursor back to the correct position it was at before nearly feels seamless though.
This behavior is copying what you did here:

  	const currentEditor = vscode.window.activeTextEditor
  	const editor = await vscode.window.showTextDocument(diffTab.input.modified, {
  		viewColumn: vscode.ViewColumn.Active,
  		preserveFocus: true,
  	})
  	if (currentEditor) {
  		await vscode.window.showTextDocument(currentEditor.document, {
  			viewColumn: currentEditor.viewColumn,
  			selection: currentEditor.selection,
  		})
  	}

but at an earlier point of the procedure.

@daniel-lxs daniel-lxs moved this from PR [Draft / In Progress] to PR [Needs Prelim Review] in Roo Code Roadmap Jul 5, 2025
@KJ7LNW
Copy link
Contributor

KJ7LNW commented Jul 6, 2025

@felixAnhalt - You have 98 commits and +/- 4000 lines (!) which is going to be very difficult to review, especially because what commits look like at the beginning is not the same as what it looks like at the end.

Please use lazygit to organize the commit hunks (hunk granularity where appropriate) into logical groupings that tell a story; it will be easiest to do that before rebasing:

Please watch this:

If during the process you discover that this really should be provided as multiple PRs with different features that build on each other, then watch this one, too:

Remember to create a backup branch before moving hunks around!

I really like this feature and I want to see it merged, so it will help to make review easy for reviewers.

For example:

  • foundational changes should happen in the earliest commits
  • changes to hunks in the same section of code should be moved down to the original commit change (unless there is a really good reason for having a later commit explain the story that modifies the same thing that was modified by an earlier commit)
  • adding checkbox settings create a large amount of churn, so please separate each individual setting into it's own commit
  • use that setting in the implementation as separate commits
  • separate commits for test changes
  • separate commits for bulk language translations (but not necessarily the original [en] translation needed for UI render)
  • etc...

@felixAnhalt
Copy link
Author

I expected something like that response.
I'll try to make myself familiar with lazygit, thank you for providing all those resources.
I fully expect this to be multiple features and therefore multiple pull requests

For future reference, the backup branch is here.

@KJ7LNW
Copy link
Contributor

KJ7LNW commented Jul 7, 2025

I'll try to make myself familiar with lazygit, thank you for providing all those resources.

I just started using it and was pretty proficient within a few hours. Mostly it is a matter of figuring out what the hot keys are: since I had trouble finding it here is a hint: m continues a rebase after you handle a merge conflict.

Also E for empty commit is available as a custom command in the wiki.

in case it is useful, this is my configuration:

git:
  autoStageResolvedConflicts: false

gui:
  skipRewordInEditorWarning: true

customCommands:
  - key: 'E'
    description: 'Add empty commit'
    context: 'commits'
    command: 'git commit --allow-empty -m "empty commit"'
    loadingText: 'Committing empty commit...'

@daniel-lxs
Copy link
Member

daniel-lxs commented Jul 10, 2025

Hi @felixAnhalt, thanks for this significant contribution and for tackling the editor focus issue. This is a substantial PR with a lot of great work.

After reviewing the changes, I have some concerns about the scope. This PR currently combines several major changes:

  • The original bug fix for editor focus.
  • A large-scale refactoring of the editing system into a provider-based architecture.
  • The introduction of a new file-based editing feature.
  • Several new settings for tab management.

While the new architecture is a definite improvement, bundling this many changes into a single PR makes it difficult to review thoroughly and increases the risk of introducing unintended side effects. For example, during testing, it appears that when fileBasedEditing is enabled, newly created or modified files are not automatically opened in the editor. Is this intentional?

We've also noted a few smaller things, which are easy fixes but highlight the challenge of catching everything in a PR of this size.

Would you be open to splitting this PR into smaller, more focused ones? For example:

  1. A PR for the core bug fix.
  2. A separate PR for the editing provider refactoring.
  3. A PR for the new settings and UI.

This would make the review process much smoother and help get these valuable changes merged more quickly. Thanks again for your work on this!

@daniel-lxs daniel-lxs moved this from PR [Needs Prelim Review] to PR [Changes Requested] in Roo Code Roadmap Jul 10, 2025
@felixAnhalt
Copy link
Author

Hey @daniel-lxs
I will split the PR into multiple ones based on the scopes you proposed. I'm sorry that it's dragging right now but I currently have a quite busy time.
I'll try to squeeze this into the weekend though.

My process will be:

Create/Update relevant issues for these scopes and reference this PR.
Create and test branches for the different scopes.
Create pull requests.
And finally, close this one here.

Thank you for your patience :)

@KJ7LNW
Copy link
Contributor

KJ7LNW commented Jul 11, 2025

I will split the PR into multiple ones based on the scopes you proposed.

One PR may end up depending on a previous, so if you decide to stack branches (with Lazygit), please put a empty commit message at the beginning of each branch so that it is easier for reviewers to tell where one branch finishes and the other picked up.

For example:

image ...

@ccrvlh
Copy link

ccrvlh commented Jul 20, 2025

@felixAnhalt let us know when you split the pr's/issues (at least logically) - would be happy to work on this as well

@felixAnhalt
Copy link
Author

hey @ccrvlh

for the initial autofocus issue #2122 there is already a new PR here.

for the two options related to the closing of tabs (autoCloseRooTabs, autoCloseAllRooTabs) after executing a diff/task there is this branch and this PR into my own forked main which is nearly finished.
Notice that I started anew to build a more intentional branch wich should also be easier to rebase/merge.

I wanted to touch the editingProvider and file-based editing this evening.

Then there are the options to granurarily decide on editing behavior still open:

  • diffViewAutoFocus for always following the newly opened diff tab (which would be the pre feat(diffViewEditor): Add autofocus feature to preserve focus on edit… #5672 behavior;current behavior)
  • openTabsInCorrectGroup to always open in the same tab group. This neccessiates adding the correct viewColumn to the showTextDocument function and to then show the document we initially were working on as humans again.
  • openTabsAtEndOfList to open at the end of the list in the current tab group. This needs us top open the last doc in the current tab group because vscode opens new tabs next to your currently active tab.

You could look at this branch as a reference implementation on how I extracted relevant code snippets from this current branch into their own.

I also moved fuzzyMatchThreshold into the FileEditingOptions because it made sense to me thematically.

Another side info: the whole part with the UserInteractionListener came from the idea, that we could let the editor autoFocus as long as the user doesn't interact with vscode and stop focusing, when the user does.

If you wanna coordinate efforts, please add me on discord.
Anyways, if you wanna take over one of the features I mentioned here, go for it :)

@felixAnhalt
Copy link
Author

@ccrvlh

here you can find the implementation for fileBasedEditing and the refactoring into a provider based pattern.

I will create an issue and PR for that tomorrow.
I will also create an issue and PR for the two options related to the closing of tabs (autoCloseRooTabs, autoCloseAllRooTabs) tomorrow.

@felixAnhalt
Copy link
Author

I think I have extracted all the core ideas of this PR into their respective issues.

To reiterate:

My proposed order of implementation:

  1. Add file-based editing mode to bypass diff view for direct writes #6001 for the new settings and change of architecture (provider based instead of using DiffViewProvider directly)
  2. Add option to disable/enable focus on diff view #6010 so that we start having varying degrees of control on the screen (from file-based "just let the AI do its thing" to "i wanna see every change live")
  3. Open Tabs in Correct Tab Group if Auto Focus Disabled #6005 and Open Tabs at the End of Tab List if Auto Focus Disabled #6006 for more granular control when Add option to disable/enable focus on diff view #6010 is set to disabled

#6003 is entirely separate.

If everyone is fine with it, I would close this one here.

@ccrvlh
Copy link

ccrvlh commented Jul 21, 2025

hey y'all. you guys are clearly on top of it, so i'll just jump in to share my perspective as user.
I came here, looking for some sort of "background mode" - eg. let roo work on some module - everything in the background, while i was working somewhere else. although focus and background are different, it seems this PR is related in terms of goal (eg. allow working in parallel).

going through the pr, my general comments:

  • File Base editing mode - that seems to make sense to me, no comments.
  • Auto close tabs - that seems simple enough as well, no comments.
  • Enable/Disable focus - i guess i'm curious on whether this is only relevant for "diff view" or if it should be global - enable/disable focus, regardless of the view
  • Open tabs in Correct Tab Group if Auto Focus Disabled - this got a bit confusing to me. as i understand, this is related to Editor Groups, but what does "correct" mean. would anyone do something "incorrect" (opposite of this setting). Also, is that directly related to "Auto Focus Disabled"? Wouldn't that be a global behavior? Even if it does steal focus, the user could chose to organize roo-related work in it's own editor group, so i'm confused about the connection between those two things. Would it make sense to have some like "Use dedicated Editor Group"? Meaning, everything Roo does is going to be on it's own editor group.
  • Open tabs at the end of tab list if auto focus disabled - i see the value on organizing the order, but confused about the relationship with auto focus. considering roo is opening tabs, then wouldn't make more sense for the default behavior be to just open the tabs at the end of tab list? auto focus is about stealing focus, and this seems to be about tab ordering.
  • (not included) the last bit I would explore - perhaps a new issue - would be a full blown background mode - meaning, none of those settings would be enable if you are in "background mode", not even seeing any tabs. I honestly don't know the API well enough to tell whether this is feasible or not, although ChatGPT does say it is through workspace.fs and workspace.writeToFile - perhaps this is similar to some of the capabilities those issues would build/edit, so though it would be worth sharing.
  • (EDIT) Last one i forgot - also not clear to me how autoCloseRooTabs differs from autoCloseAllRooTabs are there "extra" tabs that would be included in the autoCloseRooTabs? Perhaps this is just naming, idk.

you guys have been working on it for a while now, and there's a lot involved in the changes - so lmk if there's a specific topic that hasn't been explored yet about those changes, or maybe a specific logic for the organization and i'll be happy to help.

@felixAnhalt
Copy link
Author

@ccrvlh

regarding

(not included) the last bit I would explore - perhaps a new issue - would be a full blown background mode - meaning, none of those settings would be enable if you are in "background mode", not even seeing any tabs. I honestly don't know the API well enough to tell whether this is feasible or not, although ChatGPT does say it is through workspace.fs and workspace.writeToFile - perhaps this is similar to some of the capabilities those issues would build/edit, so though it would be worth sharing.

you could have a look at this PR :)
This is what the proposed file-based editing mode is essentialy.
For more information have a look at this issue, I think you'll be happy afterwards.

i guess i'm curious on whether this is only relevant for "diff view" or if it should be global - enable/disable focus, regardless of the view
you are right, it might make sense to implement this globally
Please add further discussion on that to this issue.

Open tabs in Correct Tab Group if Auto Focus Disabled - this got a bit confusing to me. as i understand, this is related to Editor Groups, but what does "correct" mean. would anyone do something "incorrect" (opposite of this setting). Also, is that directly related to "Auto Focus Disabled"? Wouldn't that be a global behavior? Even if it does steal focus, the user could chose to organize roo-related work in it's own editor group, so i'm confused about the connection between those two things. Would it make sense to have some like "Use dedicated Editor Group"? Meaning, everything Roo does is going to be on it's own editor group.

Good catch! Correct in this case means "the tab group the roo instance spawning the task was in".
Incorrect means to open new tabs wherever vscode wants to do it itself. Further discussion here please.

Open tabs at the end of tab list if auto focus disabled - i see the value on organizing the order, but confused about the relationship with auto focus. considering roo is opening tabs, then wouldn't make more sense for the default behavior be to just open the tabs at the end of tab list? auto focus is about stealing focus, and this seems to be about tab ordering.

I would argue it is tangentially related because we actually have to take focus to the document at the end of the tab list for a couple of ms (which steals focus). More about that here.

(EDIT) Last one i forgot - also not clear to me how autoCloseRooTabs differs from autoCloseAllRooTabs are there "extra" tabs that would be included in the autoCloseRooTabs? Perhaps this is just naming, idk.

Nice catch again. autoCloseRooTabs == close tabs opened by roo; autoCloseAllRooTabs == close all tabs touched by roo. More about that here..

@felixAnhalt
Copy link
Author

@ccrvlh I think what you are looking for was implemented in #6214

@github-project-automation github-project-automation bot moved this from PR [Changes Requested] to Done in Roo Code Roadmap Jul 30, 2025
@github-project-automation github-project-automation bot moved this from PR [Greenlit] to Done in Roo Code Roadmap Jul 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request PR - Changes Requested size:XXL This PR changes 1000+ lines, ignoring generated files. UI/UX UI/UX related or focused

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Edits from Roo steal editor focus, causing edited files to break

8 participants