Home Screenshots Download Order Blog* Support
User Guide Style Tab Grouping Add-ins

Tab Grouping

Introduction

By default tabs with the same name and from the same folder are grouped together. Additionally you can: .NET regular expressions are used for grouping rules. See Regular Expression Language Elements MSDN page for .NET regular expressions details.

Tab title grouping

Tab title grouping settings

Everything starts from a window title that an open document has in Visual Studio (you can check it opening the Windows dialog from the main Window menu in Visual Studio). This window title is matched with the Title grouping regex. Then <Name> and <Ext> groups checked to see if they both matched something, if not then this title remains untransformed and not grouped with other titles. Titles that successfully matched with <Name> and <Ext> are grouped with other titles having the same <Name> (<Name> grouping comparison is case sensitive unless the Group titles ignoring case differences option is turned on).

Default Title grouping regex (?<Name>(.*[/\\])?.+?)(?<Ext>\..+) matches the Name group as all symbols before the first dot after the path and matches the Ext group as the dot and all subsequent symbols. For example:

Title Name Ext
Class1.cs Class1 .cs
Class1.xaml.cs Class1 .xaml.cs
App_Code/Class1.cs App_Code/Class1 .cs
Project.X/Class1.cs Project.X/Class1 .cs

If for your project type Visual Studio doesn't add a path to titles, you can use a simpler Title grouping regex (?<Name>.+?)(?<Ext>\..+). I will use this shorter regex for the next examples.

You can use several separate Name and Ext groups, the resulting string will be concatenated from all captures. It allows you to capture multiple parts of the original tab title as the name or extension. For example, (?<Name>.+?)-(?<Name>.+?)(?<Ext>\..+) will create the MainWindow name from the Main-Window.xaml tab. (?<Ext>Test)(?<Name>.+?)(?<Ext>\..+) will create the Test.xaml extension from the TestWindow.xaml.

What if you want to group Model.cs and ModelTest.cs tabs, Controller.cs and ControllerTest.cs? First you have to decide how you want the result looks like. A tab group has the single name and several extensions, plus the tab group name should present in all original titles. This leads to the group name Model for the first pair and Controller for the second. Extensions can be different or can be the same (same extensions will be confusing, but it will work), plus each extension text should present in the corresponding original title. The simplest result fulfilling these requirements is "Model .cs Test.cs" and "Controller .cs Test.cs". A Title grouping regex producing this result is (?<Name>.+?)(?<Ext>(Test)?\..+). Alternatively, you can create a separate regex for test tabs and combine it with the default regex using the OR operator '|': (?<Name>.+?)(?<Ext>Test\..+)|(?<Name>.+?)(?<Ext>\..+).

You may want to stop some tabs to group with others. There are two ways to achieve this. First, you can limit tab grouping to explicit list of extensions: (?<Name>.+?)(?<Ext>\.(xaml|xaml\.cs))$. Or you can add a regex without <Name> and <Ext> that matches tabs that you don't want to group: .+\.[Dd]esigner\..+|(?<Name>.+?)(?<Ext>\..+).

If you want to group interface and implementation files like IService.cs and Service.cs, consider to use the ITransform add-in.

Removing parts of a tab text

It is easy to remove unimportant parts of a tab text using the Title grouping regex. First, you have to ensure that <Name> and <Ext> groups match something in the target title, then you just move unneeded parts out of <Name> and <Ext> groups. For example, to remove a path from a tab name use the following regex: (.*[/\\])?(?<Name>.+?)(?<Ext>\..+).

Attention

This regex works slightly differently than the Remove path from tab name option as it occurs before tab grouping. The remove option is implemented as a transform and occurs after tab grouping. Thus for two tabs App_code/Model.cs and App_view/Model.html using the remove path regex lets these tabs to group together, while using the remove option doesn't let these tabs to group.

To group Model.cs and ModelTest.cs tabs, but to drop .cs from Test.cs producing "Model .cs Test" use the following regex: (?<Name>.+?)(?<Ext>Test)\..+|(?<Name>.+?)(?<Ext>\..+).

Transforming tab text to be more descriptive

From an add-in for Tabs Studio you can completely change any tab name or extension using the TitleManager property and the ApplyTransforms method. For example, the Disambiguator add-in detects when two or more tabs have the same title and adds Visual Studio folder or project to titles for these tabs. And the ITransform add-in improves interface tab name representation, transforming interface titles after grouping.

Document path grouping

Path grouping settings

By default tabs are grouped only if their associated Visual Studio documents are in the same folder. This is a good default as you don't want Window1.xaml from Project1 to be grouped with Window1.xaml.cs from Project2. But sometimes really relevant files can reside in different folders. For example, it would be nice to group default.js from the Scripts folder with default.htm from the HTML folder. It can be set up in Path Grouping settings.

Having two files c:\src\Window1.xaml and c:\src\Window1.xaml.cs matching algorithm removes the common path from two files, appends '$' symbol to the end of both files and concatenates them. Resulting Window1.xaml$Window1.xaml.cs$ string is matched with Path grouping regex. If M named group matches the string then two files are combinable. If not, two full paths with two '$' symbols are concatenated (resulting in c:\src\Window1.xaml$c:\src\Window1.xaml.cs$ string) and again matched with Path grouping regex. If M named group matches the string then two files are combinable. If not, then files are not combinable.

Attention

If file paths are combinable then additional tab title grouping rules are checked - for two tabs to be grouped they need to satisfy both title grouping and path grouping rules. For documents not included in the current solution, path grouping works if you open them manually, but they can't be found as corresponding files automatically. Two paths are lexicographically "sorted", it is guaranteed that the concatenation is Project1\Window1.xaml$Project2\Window1.xaml.cs$ and not Project2\Window1.xaml.cs$Project1\Window1.xaml$.

Default Path grouping regex (?<M>^[^\\]+$) matches only when there are no back slashes in the first paths concatenation and thus groups files only from the same directory. If we try c:\Project1\Window1.xaml and c:\Project2\Window1.xaml.cs files, then the first concatenation would be Project1\Window1.xaml$Project2\Window1.xaml.cs$ - it has two back slashes and would not match default regex.

Let's see some path grouping examples:

1. Group files from the two specific folders.

Let HTML\1033\*.htm files be combinable with Scripts\1033\*.js files:

(?<M>^HTML.+?htm\$Scripts.+?js\$)|(?<M>^[^\\]+$)

2. Group files with the specific extension.

Let *.htm files from any folder be combinable with other files:

(?<M>htm\$)|(?<M>^[^\\]+$)

3. Group files from the specific folder.

Let all files from the c:\Projects\4\4\HTML folder be combinable with other files:

(?<M>c:\\Projects\\4\\4\\HTML)|(?<M>^[^\\]+$)

4. Group files from a subfolder.

Let files from the subfolder be combinable with files in upper directory (for example, c:\Projects\4\default.htm and c:\Projects\4\code\default.js):

(?<M>^[^\\]+\\[^\\]+$)|(?<M>^[^\\]+$)

5. Deny grouping for the specific extension.

Deny files with .Designer.cs extension to be combinable with other files:

(.+Designer\.cs\$)|(?<M>^[^\\]+$)

Corresponding files in different folders

As Visual Studio documents from different folders can be grouped together, the TabsStudio.Connect.OpenCorrespondingFile command and the Open context menu command can also find corresponding files in other folders (other than the current folder for the active document):

Opening corresponding file from different folder

Attention

The opened solution is scanned for files and those files that match grouping options are displayed in the context menu. Documents not included in the current solution can't be found as corresponding files automatically.