提交 dd06f3ca 编写于 作者: B Benjamin Pasero

💄

上级 82ebb108
......@@ -21,7 +21,7 @@ import { ILifecycleService, UnloadReason } from 'vs/platform/lifecycle/electron-
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { getLastActiveWindow, findBestWindowOrFolder } from 'vs/code/node/windowsUtils';
import { getLastActiveWindow, findBestWindowOrFolderForFile } from 'vs/code/node/windowsFinder';
import CommonEvent, { Emitter } from 'vs/base/common/event';
import product from 'vs/platform/node/product';
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
......@@ -345,7 +345,7 @@ export class WindowsManager implements IWindowsMainService {
// Open Files in last instance if any and flag tells us so
const fileToCheck = filesToOpen[0] || filesToCreate[0] || filesToDiff[0];
const windowOrFolder = findBestWindowOrFolder({
const bestWindowOrFolder = findBestWindowOrFolderForFile({
windows: WindowsManager.WINDOWS,
newWindow: openFilesInNewWindow,
reuseWindow: openConfig.forceReuseWindow,
......@@ -354,23 +354,24 @@ export class WindowsManager implements IWindowsMainService {
userHome: this.environmentService.userHome
});
if (windowOrFolder instanceof CodeWindow) {
windowOrFolder.focus();
// We found a suitable window to open the files within
if (bestWindowOrFolder instanceof CodeWindow) {
bestWindowOrFolder.focus();
const files = { filesToOpen, filesToCreate, filesToDiff }; // copy to object because they get reset shortly after
windowOrFolder.ready().then(readyWindow => {
bestWindowOrFolder.ready().then(readyWindow => {
readyWindow.send('vscode:openFiles', files);
});
usedWindows.push(windowOrFolder);
usedWindows.push(bestWindowOrFolder);
}
// Otherwise open instance with files
// Otherwise open a new window with the best folder to use for the file
else {
const browserWindow = this.openInBrowserWindow({
userEnv: openConfig.userEnv,
cli: openConfig.cli,
initialStartup: openConfig.initialStartup,
workspacePath: windowOrFolder,
workspacePath: bestWindowOrFolder,
filesToOpen,
filesToCreate,
filesToDiff,
......
......@@ -22,40 +22,48 @@ export interface ISimpleWindow {
/**
* Exported for testing.
*/
export interface IBestWindowOrFolderOptions<SimpleWindow extends ISimpleWindow> {
windows: SimpleWindow[];
export interface IBestWindowOrFolderOptions<W extends ISimpleWindow> {
windows: W[];
newWindow: boolean;
reuseWindow: boolean;
context: OpenContext;
filePath?: string;
userHome?: string;
vscodeFolder?: string;
codeSettingsFolder?: string;
}
export function findBestWindowOrFolder<SimpleWindow extends ISimpleWindow>({ windows, newWindow, reuseWindow, context, filePath, userHome, vscodeFolder }: IBestWindowOrFolderOptions<SimpleWindow>): SimpleWindow | string {
// OpenContext.DOCK implies newWindow unless overwritten by settings.
const findBest = filePath && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK);
const bestWindow = !newWindow && findBest && findBestWindow(windows, filePath);
const bestFolder = !newWindow && !reuseWindow && findBest && findBestFolder(filePath, userHome, vscodeFolder);
if (bestWindow && !(bestFolder && bestFolder.length > bestWindow.openedWorkspacePath.length)) {
return bestWindow;
} else if (bestFolder) {
return bestFolder;
export function findBestWindowOrFolderForFile<W extends ISimpleWindow>({ windows, newWindow, reuseWindow, context, filePath, userHome, codeSettingsFolder }: IBestWindowOrFolderOptions<W>): W | string {
if (!newWindow && filePath && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK)) {
const windowOnFilePath = findWindowOnFilePath(windows, filePath);
const folderWithCodeSettings = !reuseWindow && findFolderWithCodeSettings(filePath, userHome, codeSettingsFolder);
// Return if we found a window that has the parent of the file path opened
if (windowOnFilePath && !(folderWithCodeSettings && folderWithCodeSettings.length > windowOnFilePath.openedWorkspacePath.length)) {
return windowOnFilePath;
}
// Return if we found a parent folder with a code settings folder inside
if (folderWithCodeSettings) {
return folderWithCodeSettings;
}
}
return !newWindow ? getLastActiveWindow(windows) : null;
}
function findBestWindow<WINDOW extends ISimpleWindow>(windows: WINDOW[], filePath: string): WINDOW {
const containers = windows.filter(window => typeof window.openedWorkspacePath === 'string' && paths.isEqualOrParent(filePath, window.openedWorkspacePath, !platform.isLinux /* ignorecase */));
if (containers.length) {
return containers.sort((a, b) => -(a.openedWorkspacePath.length - b.openedWorkspacePath.length))[0];
function findWindowOnFilePath<W extends ISimpleWindow>(windows: W[], filePath: string): W {
// From all windows that have the parent of the file opened, return the window
// that has the most specific folder opened ( = longest path wins)
const windowsOnFilePath = windows.filter(window => typeof window.openedWorkspacePath === 'string' && paths.isEqualOrParent(filePath, window.openedWorkspacePath, !platform.isLinux /* ignorecase */));
if (windowsOnFilePath.length) {
return windowsOnFilePath.sort((a, b) => -(a.openedWorkspacePath.length - b.openedWorkspacePath.length))[0];
}
return null;
}
function findBestFolder(filePath: string, userHome?: string, vscodeFolder?: string): string {
function findFolderWithCodeSettings(filePath: string, userHome?: string, codeSettingsFolder?: string): string {
let folder = path.dirname(paths.normalize(filePath, true));
let homeFolder = userHome && paths.normalize(userHome, true);
if (!platform.isLinux) {
......@@ -63,38 +71,33 @@ function findBestFolder(filePath: string, userHome?: string, vscodeFolder?: stri
}
let previous = null;
try {
while (folder !== previous) {
if (isProjectFolder(folder, homeFolder, vscodeFolder)) {
return folder;
}
previous = folder;
folder = path.dirname(folder);
while (folder !== previous) {
if (hasCodeSettings(folder, homeFolder, codeSettingsFolder)) {
return folder;
}
} catch (err) {
// assume impossible to access
previous = folder;
folder = path.dirname(folder);
}
return null;
}
function isProjectFolder(folder: string, normalizedUserHome?: string, vscodeFolder = '.vscode') {
function hasCodeSettings(folder: string, normalizedUserHome?: string, codeSettingsFolder = '.vscode') {
try {
if ((platform.isLinux ? folder : folder.toLowerCase()) === normalizedUserHome) {
return fs.statSync(path.join(folder, vscodeFolder, 'settings.json')).isFile(); // ~/.vscode/extensions is used for extensions
return fs.statSync(path.join(folder, codeSettingsFolder, 'settings.json')).isFile(); // ~/.vscode/extensions is used for extensions
}
return fs.statSync(path.join(folder, vscodeFolder)).isDirectory();
return fs.statSync(path.join(folder, codeSettingsFolder)).isDirectory();
} catch (err) {
if (!(err && err.code === 'ENOENT')) {
throw err;
}
// assume impossible to access
}
return false;
}
export function getLastActiveWindow<WINDOW extends ISimpleWindow>(windows: WINDOW[]): WINDOW {
export function getLastActiveWindow<W extends ISimpleWindow>(windows: W[]): W {
if (windows.length) {
const lastFocussedDate = Math.max.apply(Math, windows.map(w => w.lastFocusTime));
const res = windows.filter(w => w.lastFocusTime === lastFocussedDate);
......
......@@ -6,7 +6,7 @@
import assert = require('assert');
import path = require('path');
import { findBestWindowOrFolder, ISimpleWindow, IBestWindowOrFolderOptions } from 'vs/code/node/windowsUtils';
import { findBestWindowOrFolderForFile, ISimpleWindow, IBestWindowOrFolderOptions } from 'vs/code/node/windowsFinder';
import { OpenContext } from 'vs/platform/windows/common/windows';
const fixturesFolder = require.toUrl('./fixtures');
......@@ -17,7 +17,7 @@ function options(custom?: Partial<IBestWindowOrFolderOptions<ISimpleWindow>>): I
newWindow: false,
reuseWindow: false,
context: OpenContext.CLI,
vscodeFolder: '_vscode',
codeSettingsFolder: '_vscode',
...custom
};
}
......@@ -31,38 +31,38 @@ const windows = [
noVscodeFolderWindow,
];
suite('WindowsUtils', () => {
suite('WindowsFinder', () => {
test('New window without folder when no windows exist', () => {
assert.equal(findBestWindowOrFolder(options()), null);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options()), null);
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')
})), null);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'),
newWindow: true // We assume this implies 'editor' work mode, might need separate CLI option later.
})), null);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'),
reuseWindow: true // We assume this implies 'editor' work mode, might need separate CLI option later.
})), null);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'),
context: OpenContext.API
})), null);
});
test('New window with folder when no windows exist', () => {
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt')
})), path.join(fixturesFolder, 'vscode_folder'));
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_folder', 'new_folder', 'new_file.txt')
})), path.join(fixturesFolder, 'vscode_folder'));
});
test('New window without folder when windows exist', () => {
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows,
filePath: path.join(fixturesFolder, 'no_vscode_folder', 'file.txt'),
newWindow: true
......@@ -70,19 +70,19 @@ suite('WindowsUtils', () => {
});
test('Last active window', () => {
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows
})), lastActiveWindow);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows,
filePath: path.join(fixturesFolder, 'no_vscode_folder2', 'file.txt')
})), lastActiveWindow);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows: [lastActiveWindow, noVscodeFolderWindow],
filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'),
reuseWindow: true
})), lastActiveWindow);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows,
filePath: path.join(fixturesFolder, 'no_vscode_folder', 'file.txt'),
context: OpenContext.API
......@@ -90,11 +90,11 @@ suite('WindowsUtils', () => {
});
test('Existing window with folder', () => {
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows,
filePath: path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')
})), noVscodeFolderWindow);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows,
filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt')
})), vscodeFolderWindow);
......@@ -102,12 +102,12 @@ suite('WindowsUtils', () => {
test('Existing window wins over vscode folder if more specific', () => {
const window = { lastFocusTime: 1, openedWorkspacePath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder') };
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window],
filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt')
})), window);
// check
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window],
filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder2', 'subfolder', 'file.txt')
})), path.join(fixturesFolder, 'vscode_folder'));
......@@ -116,7 +116,7 @@ suite('WindowsUtils', () => {
test('More specific existing window wins', () => {
const window = { lastFocusTime: 2, openedWorkspacePath: path.join(fixturesFolder, 'no_vscode_folder') };
const nestedFolderWindow = { lastFocusTime: 1, openedWorkspacePath: path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder') };
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window, nestedFolderWindow],
filePath: path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder', 'subfolder', 'file.txt')
})), nestedFolderWindow);
......@@ -124,30 +124,30 @@ suite('WindowsUtils', () => {
test('VSCode folder wins over existing window if more specific', () => {
const window = { lastFocusTime: 1, openedWorkspacePath: path.join(fixturesFolder, 'vscode_folder') };
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window],
filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder', 'subfolder', 'file.txt')
})), path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder'));
// check
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window],
filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt')
})), window);
});
test('More specific VSCode folder wins', () => {
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder', 'subfolder', 'file.txt')
})), path.join(fixturesFolder, 'vscode_folder', 'nested_vscode_folder'));
});
test('VSCode folder in home folder needs settings.json', () => {
// Because ~/.vscode/extensions is used for extensions, ~/.vscode is not enough as a hint.
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_folder', 'file.txt'),
userHome: path.join(fixturesFolder, 'vscode_folder')
})), null);
assert.equal(findBestWindowOrFolder(options({
assert.equal(findBestWindowOrFolderForFile(options({
filePath: path.join(fixturesFolder, 'vscode_home_folder', 'file.txt'),
userHome: path.join(fixturesFolder, 'vscode_home_folder')
})), path.join(fixturesFolder, 'vscode_home_folder'));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册