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

Support -w command also when code is already running

上级 136ffa69
......@@ -133,8 +133,6 @@ export interface ICommandLineArguments {
pathArguments?: string[];
workers?: number;
enablePerformance?: boolean;
firstrun?: boolean;
......@@ -146,6 +144,8 @@ export interface ICommandLineArguments {
diffMode?: boolean;
locale?: string;
waitForWindowClose?: boolean;
}
function parseCli(): ICommandLineArguments {
......@@ -195,7 +195,6 @@ function parseCli(): ICommandLineArguments {
return {
pathArguments: pathArguments,
programStart: parseNumber(args, '--timestamp', 0, 0),
workers: parseNumber(args, '--workers', -1, -1),
enablePerformance: !!opts['p'],
verboseLogging: !!opts['verbose'],
debugPluginHostPort: debugPluginHostPort,
......@@ -210,7 +209,8 @@ function parseCli(): ICommandLineArguments {
extensionDevelopmentPath: normalizePath(parseString(args, '--extensionDevelopmentPath')),
extensionTestsPath: normalizePath(parseString(args, '--extensionTestsPath')),
disableExtensions: !!opts['disableExtensions'] || !!opts['disable-extensions'],
locale: parseString(args, '--locale')
locale: parseString(args, '--locale'),
waitForWindowClose: !!opts['w'] || !!opts['wait']
};
}
......
......@@ -24,9 +24,11 @@ import {spawnSharedProcess} from 'vs/workbench/electron-main/sharedProcess';
import {Mutex} from 'windows-mutex';
export class LaunchService {
public start(args: env.ICommandLineArguments, userEnv: env.IProcessEnvironment): TPromise<void> {
public start(args: env.ICommandLineArguments, userEnv: env.IProcessEnvironment, otherInstancePid: number): TPromise<void> {
env.log('Received data from other instance', args);
let killOtherInstance = args.waitForWindowClose;
// Otherwise handle in windows manager
if (!!args.extensionDevelopmentPath) {
windows.manager.openPluginDevelopmentHostWindow({ cli: args, userEnv: userEnv });
......@@ -35,7 +37,25 @@ export class LaunchService {
} else if (args.pathArguments.length === 0) {
windows.manager.focusLastActive(args);
} else {
windows.manager.open({ cli: args, userEnv: userEnv, forceNewWindow: !args.openInSameWindow });
let usedWindows = windows.manager.open({ cli: args, userEnv: userEnv, forceNewWindow: args.waitForWindowClose || !args.openInSameWindow });
// If the other instance is waiting to be killed, we hook up a window listener if one window
// is being used and kill the other instance when that window is being closed
if (args.waitForWindowClose && usedWindows && usedWindows.length === 1) {
let windowToObserve = usedWindows[0];
killOtherInstance = false; // only scenario where the "-w" switch is supported and makes sense
let unbind = windows.onClose(id => {
if (id === windowToObserve.id) {
unbind();
process.kill(otherInstancePid);
}
});
}
}
if (killOtherInstance) {
process.kill(otherInstancePid);
}
return TPromise.as(null);
......@@ -77,7 +97,10 @@ function quit(arg?: any) {
}
}
process.exit(exitCode);
// If not in wait mode or seeing an error: exit directly
if (!env.cliArgs.waitForWindowClose || exitCode) {
process.exit(exitCode);
}
}
function main(ipcServer: Server, userEnv: env.IProcessEnvironment): void {
......@@ -200,23 +223,27 @@ function setupIPC(): TPromise<Server> {
return TPromise.wrapError(err);
}
// there's a running instance, let's connect to it
return connect(env.mainIPCHandle).then(
client => {
// Since we are the second instance, we do not want to show the dock
if (platform.isMacintosh) {
app.dock.hide();
}
// Tests from CLI require to be the only instance currently (TODO@Ben support multiple instances and output)
if (env.isTestingFromCli) {
const errorMsg = 'Running extension tests from the command line is currently only supported if no other instance of Code is running.';
console.error(errorMsg);
// Tests from CLI require to be the only instance currently (TODO@Ben support multiple instances and output)
if (env.isTestingFromCli) {
const errorMsg = 'Running extension tests from the command line is currently only supported if no other instance of Code is running.';
console.error(errorMsg);
return TPromise.wrapError(errorMsg);
}
return TPromise.wrapError(errorMsg);
}
// there's a running instance, let's connect to it
return connect(env.mainIPCHandle).then(
client => {
env.log('Sending env to running instance...');
const service = client.getService<LaunchService>('LaunchService', LaunchService);
return service.start(env.cliArgs, process.env)
return service.start(env.cliArgs, process.env, process.pid)
.then(() => client.dispose())
.then(() => TPromise.wrapError('Sent env to running instance. Terminating...'));
},
......
......@@ -60,7 +60,7 @@ export class VSCodeMenu {
// Listen to "open" & "close" event from window manager
windows.onOpen((paths) => this.onOpen(paths));
windows.onClose((remainingWindowCount) => this.onClose(remainingWindowCount));
windows.onClose(_ => this.onClose(windows.manager.getWindowCount()));
// Resolve keybindings when any first workbench is loaded
windows.onReady((win) => this.resolveKeybindings(win));
......@@ -422,7 +422,7 @@ export class VSCodeMenu {
private createOpenRecentMenuItem(path:string): Electron.MenuItem {
return new MenuItem({ label: path, click: () => {
let success = windows.manager.open({ cli: env.cliArgs, pathsToOpen: [path] });
let success = !!windows.manager.open({ cli: env.cliArgs, pathsToOpen: [path] });
if (!success) {
this.removeFromOpenedPathsList(path);
this.updateMenu();
......
......@@ -44,7 +44,7 @@ export function onReady<T>(clb: (win: window.VSCodeWindow) => void): () => void
return () => eventEmitter.removeListener(EventTypes.READY, clb);
}
export function onClose<T>(clb: (remainingWindowCount: number) => void): () => void {
export function onClose<T>(clb: (id: number) => void): () => void {
eventEmitter.addListener(EventTypes.CLOSE, clb);
return () => eventEmitter.removeListener(EventTypes.CLOSE, clb);
......@@ -429,8 +429,9 @@ export class WindowsManager {
});
}
public open(openConfig: IOpenConfiguration): boolean {
public open(openConfig: IOpenConfiguration): window.VSCodeWindow[] {
let iPathsToOpen: window.IPath[];
let usedWindows: window.VSCodeWindow[] = [];
// Find paths from provided paths if any
if (openConfig.pathsToOpen && openConfig.pathsToOpen.length > 0) {
......@@ -463,7 +464,7 @@ export class WindowsManager {
iPathsToOpen = arrays.coalesce(iPathsToOpen);
if (iPathsToOpen.length === 0) {
return false; // indicate to outside that open failed
return null; // indicate to outside that open failed
}
}
......@@ -518,12 +519,15 @@ export class WindowsManager {
readyWindow.send('vscode:installExtensions', { extensionsToInstall });
}
});
usedWindows.push(lastActiveWindow);
}
// Otherwise open instance with files
else {
configuration = this.toConfiguration(openConfig.userEnv || this.initialUserEnv, openConfig.cli, null, filesToOpen, filesToCreate, filesToDiff, extensionsToInstall);
this.openInBrowserWindow(configuration, true /* new window */);
let browserWindow = this.openInBrowserWindow(configuration, true /* new window */);
usedWindows.push(browserWindow);
openConfig.forceNewWindow = true; // any other folders to open must open in new window then
}
......@@ -535,8 +539,9 @@ export class WindowsManager {
// Check for existing instances
let windowsOnWorkspacePath = arrays.coalesce(foldersToOpen.map((iPath) => this.findWindow(iPath.workspacePath)));
if (windowsOnWorkspacePath.length > 0) {
windowsOnWorkspacePath[0].focus(); // just focus one of them
windowsOnWorkspacePath[0].ready().then((readyWindow) => {
let browserWindow = windowsOnWorkspacePath[0];
browserWindow.focus(); // just focus one of them
browserWindow.ready().then((readyWindow) => {
readyWindow.send('vscode:openFiles', {
filesToOpen: filesToOpen,
filesToCreate: filesToCreate,
......@@ -548,6 +553,8 @@ export class WindowsManager {
}
});
usedWindows.push(browserWindow);
// Reset these because we handled them
filesToOpen = [];
filesToCreate = [];
......@@ -564,7 +571,8 @@ export class WindowsManager {
}
configuration = this.toConfiguration(openConfig.userEnv || this.initialUserEnv, openConfig.cli, folderToOpen.workspacePath, filesToOpen, filesToCreate, filesToDiff, extensionsToInstall);
this.openInBrowserWindow(configuration, openConfig.forceNewWindow, openConfig.forceNewWindow ? void 0 : openConfig.windowToUse);
let browserWindow = this.openInBrowserWindow(configuration, openConfig.forceNewWindow, openConfig.forceNewWindow ? void 0 : openConfig.windowToUse);
usedWindows.push(browserWindow);
// Reset these because we handled them
filesToOpen = [];
......@@ -580,7 +588,8 @@ export class WindowsManager {
if (emptyToOpen.length > 0) {
emptyToOpen.forEach(() => {
let configuration = this.toConfiguration(openConfig.userEnv || this.initialUserEnv, openConfig.cli);
this.openInBrowserWindow(configuration, openConfig.forceNewWindow, openConfig.forceNewWindow ? void 0 : openConfig.windowToUse);
let browserWindow = this.openInBrowserWindow(configuration, openConfig.forceNewWindow, openConfig.forceNewWindow ? void 0 : openConfig.windowToUse);
usedWindows.push(browserWindow);
openConfig.forceNewWindow = true; // any other folders to open must open in new window then
});
......@@ -596,7 +605,7 @@ export class WindowsManager {
// Emit events
iPathsToOpen.forEach((iPath) => eventEmitter.emit(EventTypes.OPEN, iPath));
return true;
return arrays.distinct(usedWindows);
}
public openPluginDevelopmentHostWindow(openConfig: IOpenConfiguration): void {
......@@ -773,7 +782,7 @@ export class WindowsManager {
return [Object.create(null)];
}
private openInBrowserWindow(configuration: window.IWindowConfiguration, forceNewWindow?: boolean, windowToUse?: window.VSCodeWindow): void {
private openInBrowserWindow(configuration: window.IWindowConfiguration, forceNewWindow?: boolean, windowToUse?: window.VSCodeWindow): window.VSCodeWindow {
let vscodeWindow: window.VSCodeWindow;
if (!forceNewWindow) {
......@@ -827,6 +836,8 @@ export class WindowsManager {
vscodeWindow.load(configuration);
}
});
return vscodeWindow;
}
private getNewWindowState(configuration: window.IWindowConfiguration): window.IWindowState {
......@@ -1138,7 +1149,7 @@ export class WindowsManager {
WindowsManager.WINDOWS.splice(index, 1);
// Emit
eventEmitter.emit(EventTypes.CLOSE, WindowsManager.WINDOWS.length);
eventEmitter.emit(EventTypes.CLOSE, win.id);
}
private isPathEqual(pathA: string, pathB: string): boolean {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册