Skip to content

Commit c30266c

Browse files
author
Benjamin Pasero
committed
make window finder fit for workspaces
1 parent 87dd246 commit c30266c

3 files changed

Lines changed: 71 additions & 17 deletions

File tree

src/vs/code/electron-main/windows.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { TPromise } from "vs/base/common/winjs.base";
3232
import { IWorkspacesMainService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceSavedEvent, WORKSPACE_FILTER } from "vs/platform/workspaces/common/workspaces";
3333
import { IInstantiationService } from "vs/platform/instantiation/common/instantiation";
3434
import { mnemonicButtonLabel } from "vs/base/common/labels";
35+
import URI from "vs/base/common/uri";
3536

3637
enum WindowError {
3738
UNRESPONSIVE,
@@ -285,7 +286,7 @@ export class WindowsManager implements IWindowsMainService {
285286
buttonLabel: mnemonicButtonLabel(localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")),
286287
title: localize('saveWorkspace', "Save Workspace"),
287288
filters: WORKSPACE_FILTER,
288-
defaultPath: path.dirname(resolvedWorkspace.folders[0]) // pick the parent of the first root by default
289+
defaultPath: path.dirname(URI.parse(resolvedWorkspace.folders[0]).fsPath) // pick the parent of the first root by default
289290
});
290291

291292
if (target) {
@@ -516,12 +517,34 @@ export class WindowsManager implements IWindowsMainService {
516517
reuseWindow: openConfig.forceReuseWindow,
517518
context: openConfig.context,
518519
filePath: fileToCheck && fileToCheck.filePath,
519-
userHome: this.environmentService.userHome
520+
userHome: this.environmentService.userHome,
521+
workspaceResolver: workspace => this.workspacesService.resolveWorkspaceSync(workspace.configPath)
520522
});
521523

522-
// We found a suitable window to open the files within: send the files to open over
523-
if (bestWindowOrFolder instanceof CodeWindow && bestWindowOrFolder.openedFolderPath) {
524-
foldersToOpen.push(bestWindowOrFolder.openedFolderPath);
524+
// We found a window to open the files in
525+
if (bestWindowOrFolder instanceof CodeWindow) {
526+
527+
// Window is workspace
528+
if (bestWindowOrFolder.openedWorkspace) {
529+
workspacesToOpen.push(bestWindowOrFolder.openedWorkspace);
530+
}
531+
532+
// Window is single folder
533+
else if (bestWindowOrFolder.openedFolderPath) {
534+
foldersToOpen.push(bestWindowOrFolder.openedFolderPath);
535+
}
536+
537+
// Window is empty
538+
else {
539+
540+
// Do open files
541+
usedWindows.push(this.doOpenFilesInExistingWindow(bestWindowOrFolder, filesToOpen, filesToCreate, filesToDiff));
542+
543+
// Reset these because we handled them
544+
filesToOpen = [];
545+
filesToCreate = [];
546+
filesToDiff = [];
547+
}
525548
}
526549

527550
// We found a suitable folder to open: add it to foldersToOpen

src/vs/code/node/windowsFinder.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import * as fs from 'fs';
1010
import * as platform from 'vs/base/common/platform';
1111
import * as paths from 'vs/base/common/paths';
1212
import { OpenContext } from 'vs/platform/windows/common/windows';
13-
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from "vs/platform/workspaces/common/workspaces";
13+
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IStoredWorkspace } from "vs/platform/workspaces/common/workspaces";
14+
import URI from "vs/base/common/uri";
1415

1516
export interface ISimpleWindow {
1617
openedWorkspace?: IWorkspaceIdentifier;
@@ -28,19 +29,25 @@ export interface IBestWindowOrFolderOptions<W extends ISimpleWindow> {
2829
filePath?: string;
2930
userHome?: string;
3031
codeSettingsFolder?: string;
32+
workspaceResolver: (workspace: IWorkspaceIdentifier) => IStoredWorkspace;
3133
}
3234

33-
export function findBestWindowOrFolderForFile<W extends ISimpleWindow>({ windows, newWindow, reuseWindow, context, filePath, userHome, codeSettingsFolder }: IBestWindowOrFolderOptions<W>): W | string {
35+
export function findBestWindowOrFolderForFile<W extends ISimpleWindow>({ windows, newWindow, reuseWindow, context, filePath, userHome, codeSettingsFolder, workspaceResolver }: IBestWindowOrFolderOptions<W>): W | string {
3436
if (!newWindow && filePath && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK)) {
35-
const windowOnFilePath = findWindowOnFilePath(windows, filePath);
36-
const folderWithCodeSettings = !reuseWindow && findFolderWithCodeSettings(filePath, userHome, codeSettingsFolder);
37+
const windowOnFilePath = findWindowOnFilePath(windows, filePath, workspaceResolver);
38+
39+
// 1) window wins if it has a workspace opened
40+
if (windowOnFilePath && !!windowOnFilePath.openedWorkspace) {
41+
return windowOnFilePath;
42+
}
3743

38-
// Return if we found a window that has the parent of the file path opened
44+
// 2) window wins if it has a folder opened that is more specific than settings folder
45+
const folderWithCodeSettings = !reuseWindow && findFolderWithCodeSettings(filePath, userHome, codeSettingsFolder);
3946
if (windowOnFilePath && !(folderWithCodeSettings && folderWithCodeSettings.length > windowOnFilePath.openedFolderPath.length)) {
4047
return windowOnFilePath;
4148
}
4249

43-
// Return if we found a parent folder with a code settings folder inside
50+
// 3) finally return path to folder with settings
4451
if (folderWithCodeSettings) {
4552
return folderWithCodeSettings;
4653
}
@@ -49,13 +56,22 @@ export function findBestWindowOrFolderForFile<W extends ISimpleWindow>({ windows
4956
return !newWindow ? getLastActiveWindow(windows) : null;
5057
}
5158

52-
function findWindowOnFilePath<W extends ISimpleWindow>(windows: W[], filePath: string): W {
59+
function findWindowOnFilePath<W extends ISimpleWindow>(windows: W[], filePath: string, workspaceResolver: (workspace: IWorkspaceIdentifier) => IStoredWorkspace): W {
60+
61+
// First check for windows with workspaces that have a parent folder of the provided path opened
62+
const workspaceWindows = windows.filter(window => !!window.openedWorkspace);
63+
for (let i = 0; i < workspaceWindows.length; i++) {
64+
const window = workspaceWindows[i];
65+
const resolvedWorkspace = workspaceResolver(window.openedWorkspace);
66+
if (resolvedWorkspace && resolvedWorkspace.folders.some(folderUri => paths.isEqualOrParent(filePath, URI.parse(folderUri).fsPath, !platform.isLinux /* ignorecase */))) {
67+
return window;
68+
}
69+
}
5370

54-
// From all windows that have the parent of the file opened, return the window
55-
// that has the most specific folder opened ( = longest path wins)
56-
const windowsOnFilePath = windows.filter(window => typeof window.openedFolderPath === 'string' && paths.isEqualOrParent(filePath, window.openedFolderPath, !platform.isLinux /* ignorecase */));
57-
if (windowsOnFilePath.length) {
58-
return windowsOnFilePath.sort((a, b) => -(a.openedFolderPath.length - b.openedFolderPath.length))[0];
71+
// Then go with single folder windows that are parent of the provided file path
72+
const singleFolderWindowsOnFilePath = windows.filter(window => typeof window.openedFolderPath === 'string' && paths.isEqualOrParent(filePath, window.openedFolderPath, !platform.isLinux /* ignorecase */));
73+
if (singleFolderWindowsOnFilePath.length) {
74+
return singleFolderWindowsOnFilePath.sort((a, b) => -(a.openedFolderPath.length - b.openedFolderPath.length))[0];
5975
}
6076

6177
return null;

src/vs/code/test/node/windowsFinder.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@ import assert = require('assert');
88
import path = require('path');
99
import { findBestWindowOrFolderForFile, ISimpleWindow, IBestWindowOrFolderOptions } from 'vs/code/node/windowsFinder';
1010
import { OpenContext } from 'vs/platform/windows/common/windows';
11+
import { IWorkspaceIdentifier } from "vs/platform/workspaces/common/workspaces";
1112

1213
const fixturesFolder = require.toUrl('./fixtures');
1314

15+
const testWorkspace: IWorkspaceIdentifier = {
16+
id: Date.now().toString(),
17+
configPath: path.join(fixturesFolder, 'workspaces.json')
18+
};
19+
1420
function options(custom?: Partial<IBestWindowOrFolderOptions<ISimpleWindow>>): IBestWindowOrFolderOptions<ISimpleWindow> {
1521
return {
1622
windows: [],
1723
newWindow: false,
1824
reuseWindow: false,
1925
context: OpenContext.CLI,
2026
codeSettingsFolder: '_vscode',
27+
workspaceResolver: workspace => { return workspace === testWorkspace ? { id: testWorkspace.id, folders: [path.join(fixturesFolder, 'vscode_workspace_1_folder'), path.join(fixturesFolder, 'vscode_workspace_2_folder')] } : null; },
2128
...custom
2229
};
2330
}
@@ -152,4 +159,12 @@ suite('WindowsFinder', () => {
152159
userHome: path.join(fixturesFolder, 'vscode_home_folder')
153160
})), path.join(fixturesFolder, 'vscode_home_folder'));
154161
});
162+
163+
test('Workspace folder wins', () => {
164+
const window = { lastFocusTime: 1, openedWorkspace: testWorkspace };
165+
assert.equal(findBestWindowOrFolderForFile(options({
166+
windows: [window],
167+
filePath: path.join(fixturesFolder, 'vscode_workspace_2_folder', 'nested_vscode_folder', 'subfolder', 'file.txt')
168+
})), window);
169+
});
155170
});

0 commit comments

Comments
 (0)