mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-04 07:15:54 +01:00
Open parent folder with .vscode when opening files from CLI or desktop (fixes #20671)
This commit is contained in:
123
src/vs/code/node/windowsUtils.ts
Normal file
123
src/vs/code/node/windowsUtils.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'original-fs';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
|
||||
export enum OpenContext {
|
||||
|
||||
// opening when running from the command line
|
||||
CLI,
|
||||
|
||||
// macOS only: opening from the dock (also when opening files to a running instance from desktop)
|
||||
DOCK,
|
||||
|
||||
// opening from the main application window
|
||||
MENU,
|
||||
|
||||
// opening from a file or folder dialog
|
||||
DIALOG,
|
||||
|
||||
// opening from the OS's UI
|
||||
DESKTOP,
|
||||
|
||||
// opening through the API
|
||||
API
|
||||
}
|
||||
|
||||
/**
|
||||
* Exported subset of VSCodeWindow for testing.
|
||||
*/
|
||||
export interface ISimpleWindow {
|
||||
openedWorkspacePath: string;
|
||||
lastFocusTime: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exported for testing.
|
||||
*/
|
||||
export interface IBestWindowOrFolderOptions<WINDOW> {
|
||||
windows: WINDOW[];
|
||||
newWindow: boolean;
|
||||
reuseWindow: boolean;
|
||||
context: OpenContext;
|
||||
filePath?: string;
|
||||
userHome?: string;
|
||||
vscodeFolder?: string;
|
||||
}
|
||||
|
||||
export function findBestWindowOrFolder<WINDOW extends ISimpleWindow>({ windows, newWindow, reuseWindow, context, filePath, userHome, vscodeFolder }: IBestWindowOrFolderOptions<WINDOW>): WINDOW | 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;
|
||||
}
|
||||
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));
|
||||
if (containers.length) {
|
||||
return containers.sort((a, b) => -(a.openedWorkspacePath.length - b.openedWorkspacePath.length))[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findBestFolder(filePath: string, userHome?: string, vscodeFolder?: string): string {
|
||||
let folder = path.dirname(paths.normalize(filePath, true));
|
||||
let homeFolder = userHome && paths.normalize(userHome, true);
|
||||
if (!platform.isLinux) {
|
||||
homeFolder = homeFolder && homeFolder.toLowerCase();
|
||||
}
|
||||
let previous = null;
|
||||
try {
|
||||
while (folder !== previous) {
|
||||
if (isProjectFolder(folder, homeFolder, vscodeFolder)) {
|
||||
return folder;
|
||||
}
|
||||
previous = folder;
|
||||
folder = path.dirname(folder);
|
||||
}
|
||||
} catch (err) {
|
||||
// assume impossible to access
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isProjectFolder(folder: string, normalizedUserHome?: string, vscodeFolder = '.vscode') {
|
||||
try {
|
||||
if ((platform.isLinux ? folder : folder.toLowerCase()) === normalizedUserHome) {
|
||||
// ~/.vscode/extensions is used for extensions
|
||||
return fs.statSync(path.join(folder, vscodeFolder, 'settings.json')).isFile();
|
||||
} else {
|
||||
return fs.statSync(path.join(folder, vscodeFolder)).isDirectory();
|
||||
}
|
||||
} catch (err) {
|
||||
if (!(err && err.code === 'ENOENT')) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getLastActiveWindow<WINDOW extends ISimpleWindow>(windows: WINDOW[]): WINDOW {
|
||||
if (windows.length) {
|
||||
const lastFocussedDate = Math.max.apply(Math, windows.map(w => w.lastFocusTime));
|
||||
const res = windows.filter(w => w.lastFocusTime === lastFocussedDate);
|
||||
if (res && res.length) {
|
||||
return res[0];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user