From 49750bbe6848756c7c6b268b32f39a7d2ede5f2c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 13 Sep 2016 18:05:39 +0200 Subject: [PATCH 01/23] Implement #4719 --- .../contrib/find/common/findController.ts | 20 ++++++---- .../editor/contrib/find/common/findModel.ts | 15 +++++++ .../search/browser/search.contribution.ts | 19 +++++---- .../parts/search/browser/searchActions.ts | 39 +++++++++++++++++++ .../parts/search/browser/searchViewlet.ts | 15 +++++++ .../parts/search/browser/searchWidget.ts | 7 +++- .../parts/search/common/constants.ts | 5 +++ 7 files changed, 104 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 8d0bd01fab0..be75e59688a 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -14,7 +14,7 @@ import {Selection} from 'vs/editor/common/core/selection'; import * as strings from 'vs/base/common/strings'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {editorAction, commonEditorContribution, ServicesAccessor, EditorAction, EditorCommand, CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {FIND_IDS, FindModelBoundToEditorModel} from 'vs/editor/contrib/find/common/findModel'; +import {FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding} from 'vs/editor/contrib/find/common/findModel'; import {FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState} from 'vs/editor/contrib/find/common/findState'; import {DocumentHighlightProviderRegistry} from 'vs/editor/common/modes'; import {RunOnceScheduler, Delayer} from 'vs/base/common/async'; @@ -920,8 +920,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ kbOpts: { weight: CommonEditorRegistry.commandWeight(5), kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.KEY_C, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } + primary: ToggleCaseSensitiveKeybinding.primary, + mac: ToggleCaseSensitiveKeybinding.mac, + win: ToggleCaseSensitiveKeybinding.win, + linux: ToggleCaseSensitiveKeybinding.linux } })); @@ -932,8 +934,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ kbOpts: { weight: CommonEditorRegistry.commandWeight(5), kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.KEY_W, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } + primary: ToggleWholeWordKeybinding.primary, + mac: ToggleWholeWordKeybinding.mac, + win: ToggleWholeWordKeybinding.win, + linux: ToggleWholeWordKeybinding.linux } })); @@ -944,8 +948,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ kbOpts: { weight: CommonEditorRegistry.commandWeight(5), kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.KEY_R, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } + primary: ToggleRegexKeybinding.primary, + mac: ToggleRegexKeybinding.mac, + win: ToggleRegexKeybinding.win, + linux: ToggleRegexKeybinding.linux } })); diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 542e7c2234e..bb0796feda1 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -16,6 +16,21 @@ import {FindDecorations} from './findDecorations'; import {FindReplaceState, FindReplaceStateChangedEvent} from './findState'; import {ReplaceAllCommand} from './replaceAllCommand'; import {Selection} from 'vs/editor/common/core/selection'; +import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; +import {IKeybindings} from 'vs/platform/keybinding/common/keybinding'; + +export const ToggleCaseSensitiveKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.KEY_C, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } +}; +export const ToggleWholeWordKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.KEY_W, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } +}; +export const ToggleRegexKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.KEY_R, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } +}; export const FIND_IDS = { StartFindAction: 'actions.find', diff --git a/src/vs/workbench/parts/search/browser/search.contribution.ts b/src/vs/workbench/parts/search/browser/search.contribution.ts index e5215a75ab6..782ac6ec7b5 100644 --- a/src/vs/workbench/parts/search/browser/search.contribution.ts +++ b/src/vs/workbench/parts/search/browser/search.contribution.ts @@ -25,11 +25,12 @@ import {IKeybindings} from 'vs/platform/keybinding/common/keybinding'; import {IQuickOpenService} from 'vs/workbench/services/quickopen/common/quickOpenService'; import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; -import {OpenSearchViewletAction, ReplaceInFilesAction, ShowNextSearchTermAction, ShowPreviousSearchTermAction, FocusNextInputAction, FocusPreviousInputAction} from 'vs/workbench/parts/search/browser/searchActions'; +import * as searchActions from 'vs/workbench/parts/search/browser/searchActions'; import * as Constants from 'vs/workbench/parts/search/common/constants'; import { registerContributions as replaceContributions } from 'vs/workbench/parts/search/browser/replaceContributions'; import { registerContributions as searchWidgetContributions } from 'vs/workbench/parts/search/browser/searchWidget'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding } from 'vs/editor/contrib/find/common/findModel'; replaceContributions(); searchWidgetContributions(); @@ -118,13 +119,13 @@ const openSearchViewletKb: IKeybindings = { }; (Registry.as(ActionExtensions.WorkbenchActions)).registerWorkbenchAction( - new SyncActionDescriptor(OpenSearchViewletAction, OpenSearchViewletAction.ID, OpenSearchViewletAction.LABEL, openSearchViewletKb), + new SyncActionDescriptor(searchActions.OpenSearchViewletAction, searchActions.OpenSearchViewletAction.ID, searchActions.OpenSearchViewletAction.LABEL, openSearchViewletKb), 'View: Show Search', nls.localize('view', "View") ); (Registry.as(ActionExtensions.WorkbenchActions)).registerWorkbenchAction( - new SyncActionDescriptor(ReplaceInFilesAction, ReplaceInFilesAction.ID, ReplaceInFilesAction.LABEL, { + new SyncActionDescriptor(searchActions.ReplaceInFilesAction, searchActions.ReplaceInFilesAction.ID, searchActions.ReplaceInFilesAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H }), 'Replace in Files' @@ -165,22 +166,26 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ShowAllSymbolsAction, primary: KeyMod.CtrlCmd | KeyCode.KEY_T }), 'Show All Symbols'); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchTermAction, ShowNextSearchTermAction.ID, ShowNextSearchTermAction.LABEL, { +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowNextSearchTermAction, searchActions.ShowNextSearchTermAction.ID, searchActions.ShowNextSearchTermAction.LABEL, { primary: KeyMod.Alt | KeyCode.DownArrow }, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchTermAction, ShowPreviousSearchTermAction.ID, ShowPreviousSearchTermAction.LABEL, { +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowPreviousSearchTermAction, searchActions.ShowPreviousSearchTermAction.ID, searchActions.ShowPreviousSearchTermAction.LABEL, { primary: KeyMod.Alt | KeyCode.UpArrow }, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); -registry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextInputAction, FocusNextInputAction.ID, FocusNextInputAction.LABEL, { +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FocusNextInputAction, searchActions.FocusNextInputAction.ID, searchActions.FocusNextInputAction.LABEL, { primary: KeyCode.DownArrow }, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.InputBoxFocussedKey)), ''); -registry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousInputAction, FocusPreviousInputAction.ID, FocusPreviousInputAction.LABEL, { +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FocusPreviousInputAction, searchActions.FocusPreviousInputAction.ID, searchActions.FocusPreviousInputAction.LABEL, { primary: KeyCode.UpArrow }, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.InputBoxFocussedKey, Constants.SearchInputBoxFocussedKey.toNegated())), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ToggleCaseSensitiveAction, Constants.ToggleCaseSensitiveActionId, '', ToggleCaseSensitiveKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ToggleWholeWordAction, Constants.ToggleWholeWordActionId, '', ToggleWholeWordKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ToggleRegexAction, Constants.ToggleRegexActionId, '', ToggleRegexKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); + // Configuration const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ diff --git a/src/vs/workbench/parts/search/browser/searchActions.ts b/src/vs/workbench/parts/search/browser/searchActions.ts index a0660b81c59..ec7c97d3bb3 100644 --- a/src/vs/workbench/parts/search/browser/searchActions.ts +++ b/src/vs/workbench/parts/search/browser/searchActions.ts @@ -39,6 +39,45 @@ export function appendKeyBindingLabel(label: string, keyBinding: any, keyBinding return label + ' (' + keyBindingService2.getLabelFor(keyBinding) + ')'; } +export class ToggleCaseSensitiveAction extends Action { + + constructor(id: string, label: string, @IViewletService private viewletService: IViewletService) { + super(id, label); + } + + public run(): TPromise { + let searchViewlet = this.viewletService.getActiveViewlet(); + searchViewlet.toggleCaseSensitive(); + return TPromise.as(null); + } +} + +export class ToggleWholeWordAction extends Action { + + constructor(id: string, label: string, @IViewletService private viewletService: IViewletService) { + super(id, label); + } + + public run(): TPromise { + let searchViewlet = this.viewletService.getActiveViewlet(); + searchViewlet.toggleWholeWords(); + return TPromise.as(null); + } +} + +export class ToggleRegexAction extends Action { + + constructor(id: string, label: string, @IViewletService private viewletService: IViewletService) { + super(id, label); + } + + public run(): TPromise { + let searchViewlet = this.viewletService.getActiveViewlet(); + searchViewlet.toggleRegex(); + return TPromise.as(null); + } +} + export class ShowNextSearchTermAction extends Action { public static ID = 'search.history.showNext'; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index d33bd665e66..9f251cce6af 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -617,6 +617,21 @@ export class SearchViewlet extends Viewlet { return dom.hasClass(this.queryDetails, 'more'); } + public toggleCaseSensitive(): void { + this.searchWidget.searchInput.setCaseSensitive(!this.searchWidget.searchInput.getCaseSensitive()); + this.onQueryChanged(true, true); + } + + public toggleWholeWords(): void { + this.searchWidget.searchInput.setWholeWords(!this.searchWidget.searchInput.getWholeWords()); + this.onQueryChanged(true, true); + } + + public toggleRegex(): void { + this.searchWidget.searchInput.setRegex(!this.searchWidget.searchInput.getRegex()); + this.onQueryChanged(true, true); + } + public toggleFileTypes(moveFocus?: boolean, show?: boolean, skipLayout?: boolean, reverse?: boolean): void { let cls = 'more'; show = typeof show === 'undefined' ? !dom.hasClass(this.queryDetails, cls) : Boolean(show); diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index b6827643e92..3b66bedd7b6 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -201,7 +201,10 @@ export class SearchWidget extends Widget { let inputOptions: IFindInputOptions = { label: nls.localize('label.Search', 'Search: Type Search Term and press Enter to search or Escape to cancel'), validation: (value: string) => this.validatSearchInput(value), - placeholder: nls.localize('search.placeHolder', "Search") + placeholder: nls.localize('search.placeHolder', "Search"), + appendCaseSensitiveLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybindings(Constants.ToggleCaseSensitiveActionId)[0], this.keyBindingService2), + appendWholeWordsLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybindings(Constants.ToggleWholeWordActionId)[0], this.keyBindingService2), + appendRegexLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybindings(Constants.ToggleRegexActionId)[0], this.keyBindingService2) }; let searchInputContainer= dom.append(parent, dom.$('.search-container.input-box')); @@ -350,7 +353,7 @@ export class SearchWidget extends Widget { export function registerContributions() { KeybindingsRegistry.registerCommandAndKeybindingRule({id: ReplaceAllAction.ID, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: ContextKeyExpr.and(ContextKeyExpr.has('searchViewletVisible'), Constants.ReplaceActiveKey, CONTEXT_FIND_WIDGET_NOT_VISIBLE), + when: ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.ReplaceActiveKey, CONTEXT_FIND_WIDGET_NOT_VISIBLE), primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.Enter, handler: accessor => { if (isSearchViewletFocussed(accessor.get(IViewletService))) { diff --git a/src/vs/workbench/parts/search/common/constants.ts b/src/vs/workbench/parts/search/common/constants.ts index 94d8751d55f..678d59c02dd 100644 --- a/src/vs/workbench/parts/search/common/constants.ts +++ b/src/vs/workbench/parts/search/common/constants.ts @@ -7,6 +7,11 @@ import {RawContextKey} from 'vs/platform/contextkey/common/contextkey'; export const VIEWLET_ID = 'workbench.view.search'; +export const ToggleCaseSensitiveActionId = 'toggleSearchCaseSensitive'; +export const ToggleWholeWordActionId = 'toggleSearchWholeWord'; +export const ToggleRegexActionId = 'toggleSearchRegex'; + + export const SearchViewletVisibleKey = new RawContextKey('searchViewletVisible', true); export const InputBoxFocussedKey = new RawContextKey('inputBoxFocus', false); export const SearchInputBoxFocussedKey = new RawContextKey('searchInputBoxFocus', false); From da4a174b3da5e56a437beb673cb0565b91e5db7a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 13 Sep 2016 10:53:10 -0700 Subject: [PATCH 02/23] Focus panel when kill command is run Fixes #11972 --- .../parts/terminal/electron-browser/terminalActions.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 9f622245cae..1db5b02b6c5 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -47,6 +47,9 @@ export class KillTerminalAction extends Action { let terminalInstance = this.terminalService.getActiveInstance(); if (terminalInstance) { this.terminalService.getActiveInstance().dispose(); + if (this.terminalService.terminalInstances.length > 0) { + this.terminalService.showPanel(true); + } } return TPromise.as(void 0); } From 296699027228ddf65642b59730da775c90efa78a Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Tue, 13 Sep 2016 14:07:16 -0700 Subject: [PATCH 03/23] Add shellArgs. Fix #10917 --- src/vs/vscode.d.ts | 2 +- src/vs/workbench/api/node/extHost.api.impl.ts | 4 ++-- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/api/node/extHostTerminalService.ts | 9 +++++---- src/vs/workbench/api/node/mainThreadTerminalService.ts | 4 ++-- .../parts/terminal/electron-browser/terminal.ts | 2 +- .../terminal/electron-browser/terminalInstance.ts | 10 ++++++---- .../parts/terminal/electron-browser/terminalService.ts | 10 +++++++--- 8 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 33044f955f6..024de4ba099 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3500,7 +3500,7 @@ declare namespace vscode { * @param shellPath Optional path to a custom shell executable to be used in the terminal. * @return A new Terminal. */ - export function createTerminal(name?: string, shellPath?: string): Terminal; + export function createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): Terminal; } /** diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 0533d77c825..8190d313b37 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -260,8 +260,8 @@ export class ExtHostAPIImplementation { createOutputChannel(name: string): vscode.OutputChannel { return extHostOutputService.createOutputChannel(name); }, - createTerminal(name?: string, shellPath?: string): vscode.Terminal { - return extHostTerminalService.createTerminal(name, shellPath); + createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { + return extHostTerminalService.createTerminal(name, shellPath, shellArgs); } }; diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 287936c1410..2b0c5345d70 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -153,7 +153,7 @@ export abstract class MainThreadOutputServiceShape { } export abstract class MainThreadTerminalServiceShape { - $createTerminal(name?: string, shellPath?: string): number { throw ni(); } + $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): number { throw ni(); } $dispose(terminalId: number): void { throw ni(); } $hide(terminalId: number): void { throw ni(); } $sendText(terminalId: number, text: string, addNewLine: boolean): void { throw ni(); } diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 74d0de54efa..79e19be8d68 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -12,16 +12,17 @@ export class ExtHostTerminal implements vscode.Terminal { public _name: string; public _shellPath: string; + public _shellArgs: string[]; private _id: number; private _proxy: MainThreadTerminalServiceShape; private _disposed: boolean; - constructor(proxy: MainThreadTerminalServiceShape, id: number, name?: string, shellPath?: string) { + constructor(proxy: MainThreadTerminalServiceShape, id: number, name?: string, shellPath?: string, shellArgs?: string[]) { this._name = name; this._shellPath = shellPath; this._proxy = proxy; - this._id = this._proxy.$createTerminal(name, shellPath); + this._id = this._proxy.$createTerminal(name, shellPath, shellArgs); } public get name(): string { @@ -66,7 +67,7 @@ export class ExtHostTerminalService { this._proxy = threadService.get(MainContext.MainThreadTerminalService); } - public createTerminal(name?: string, shellPath?: string): vscode.Terminal { - return new ExtHostTerminal(this._proxy, -1, name, shellPath); + public createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { + return new ExtHostTerminal(this._proxy, -1, name, shellPath, shellArgs); } } diff --git a/src/vs/workbench/api/node/mainThreadTerminalService.ts b/src/vs/workbench/api/node/mainThreadTerminalService.ts index 94d11f0aa92..67c0c1bd8fe 100644 --- a/src/vs/workbench/api/node/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/node/mainThreadTerminalService.ts @@ -19,8 +19,8 @@ export class MainThreadTerminalService extends MainThreadTerminalServiceShape { super(); } - public $createTerminal(name?: string, shellPath?: string): number { - return this.terminalService.createInstance(name, shellPath).id; + public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): number { + return this.terminalService.createInstance(name, shellPath, shellArgs).id; } public $show(terminalId: number, preserveFocus: boolean): void { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.ts index 794b7a2ce95..1c558a60f49 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.ts @@ -62,7 +62,7 @@ export interface ITerminalService { onInstanceTitleChanged: Event; terminalInstances: ITerminalInstance[]; - createInstance(name?: string, shellPath?: string): ITerminalInstance; + createInstance(name?: string, shellPath?: string, shellArgs?: string[]): ITerminalInstance; getInstanceFromId(terminalId: number): ITerminalInstance; getInstanceLabels(): string[]; getActiveInstance(): ITerminalInstance; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index f895e8ee838..e703cdaaeab 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -52,13 +52,13 @@ export class TerminalInstance implements ITerminalInstance { private container: HTMLElement, private workspace: IWorkspace, name: string, - shellPath: string, + shell: IShell, @IKeybindingService private keybindingService: IKeybindingService, @IMessageService private messageService: IMessageService ) { this._id = TerminalInstance.ID_COUNTER++; this._onTitleChanged = new Emitter(); - this.createProcess(workspace, name, shellPath); + this.createProcess(workspace, name, shell); if (container) { this.attachToElement(container); @@ -210,9 +210,11 @@ export class TerminalInstance implements ITerminalInstance { return typeof data === 'string' ? data.replace(TerminalInstance.EOL_REGEX, os.EOL) : data; } - private createProcess(workspace: IWorkspace, name?: string, shellPath?: string) { + private createProcess(workspace: IWorkspace, name?: string, shell?: IShell) { let locale = this.configHelper.isSetLocaleVariables() ? platform.locale : undefined; - let shell = shellPath ? { executable: shellPath, args: [] } : this.configHelper.getShell(); + if (!shell) { + shell = this.configHelper.getShell(); + } let env = TerminalInstance.createTerminalEnv(process.env, shell, workspace, locale); this._title = name ? name : ''; this.process = cp.fork('./terminalProcess', [], { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index b9bc29f817d..fcfc0a8f8a0 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -14,7 +14,7 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; import { ITerminalInstance, ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/electron-browser/terminal'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { TPromise } from 'vs/base/common/winjs.base'; -import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; +import { TerminalConfigHelper, IShell } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/terminalInstance'; export class TerminalService implements ITerminalService { @@ -51,7 +51,11 @@ export class TerminalService implements ITerminalService { this._configHelper = this.instantiationService.createInstance(TerminalConfigHelper, platform.platform); } - public createInstance(name?: string, shellPath?: string): ITerminalInstance { + public createInstance(name?: string, shellPath?: string, shellArgs?: string[]): ITerminalInstance { + let shell: IShell = { + executable: shellPath, + args: shellArgs + }; let terminalInstance = this.instantiationService.createInstance(TerminalInstance, this.terminalFocusContextKey, this.onTerminalInstanceDispose.bind(this), @@ -59,7 +63,7 @@ export class TerminalService implements ITerminalService { this.terminalContainer, this.workspaceContextService.getWorkspace(), name, - shellPath); + shell); terminalInstance.addDisposable(terminalInstance.onTitleChanged(this._onInstanceTitleChanged.fire, this._onInstanceTitleChanged)); this.terminalInstances.push(terminalInstance); if (this.terminalInstances.length === 1) { From 9da873d64f19eb3f17d1bac52a3db226cbf639c1 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Tue, 13 Sep 2016 14:21:45 -0700 Subject: [PATCH 04/23] Address PR comments --- src/vs/workbench/api/node/extHostTerminalService.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 79e19be8d68..04032aea8b3 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -11,8 +11,6 @@ import {MainContext, MainThreadTerminalServiceShape} from './extHost.protocol'; export class ExtHostTerminal implements vscode.Terminal { public _name: string; - public _shellPath: string; - public _shellArgs: string[]; private _id: number; private _proxy: MainThreadTerminalServiceShape; @@ -20,7 +18,6 @@ export class ExtHostTerminal implements vscode.Terminal { constructor(proxy: MainThreadTerminalServiceShape, id: number, name?: string, shellPath?: string, shellArgs?: string[]) { this._name = name; - this._shellPath = shellPath; this._proxy = proxy; this._id = this._proxy.$createTerminal(name, shellPath, shellArgs); } From b893f4916457020fe74e43f82d4e67af00b3c8b4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 13 Sep 2016 14:49:31 -0700 Subject: [PATCH 05/23] Fix various issues when the terminal was not open on launch Fixes #11969 --- .../parts/terminal/electron-browser/media/terminal.css | 1 + .../parts/terminal/electron-browser/terminalInstance.ts | 8 +++++++- .../parts/terminal/electron-browser/terminalPanel.ts | 2 ++ .../parts/terminal/electron-browser/terminalService.ts | 3 +-- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css index 132831e836b..35c4f0f5188 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css @@ -22,6 +22,7 @@ display: flex; padding: 0 20px; flex-grow: 1; + width: 100%; } .monaco-workbench .panel.integrated-terminal .terminal-wrapper { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index e703cdaaeab..56365a184f0 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -38,6 +38,7 @@ export class TerminalInstance implements ITerminalInstance { public get onTitleChanged(): Event { return this._onTitleChanged.event; } private isExiting: boolean = false; + private isVisible: boolean = false; private toDispose: lifecycle.IDisposable[] = []; private skipTerminalKeybindings: Keybinding[] = []; private process: cp.ChildProcess; @@ -74,6 +75,7 @@ export class TerminalInstance implements ITerminalInstance { throw new Error('The terminal instance has already been attached to a container'); } + this.container = container; this.wrapperElement = document.createElement('div'); DOM.addClass(this.wrapperElement, 'terminal-wrapper'); this.xtermElement = document.createElement('div'); @@ -139,6 +141,7 @@ export class TerminalInstance implements ITerminalInstance { this.container.appendChild(this.wrapperElement); this.layout(new Dimension(this.container.offsetWidth, this.container.offsetHeight)); + this.setVisible(this.isVisible); } public copySelection(): void { @@ -195,7 +198,10 @@ export class TerminalInstance implements ITerminalInstance { } public setVisible(visible: boolean): void { - DOM.toggleClass(this.wrapperElement, 'active', visible); + this.isVisible = visible; + if (this.wrapperElement) { + DOM.toggleClass(this.wrapperElement, 'active', visible); + } } public scrollDown(): void { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 5a6b61185ad..333101d492d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -72,6 +72,8 @@ export class TerminalPanel extends Panel { this.updateTheme(); this.updateConfig(); + // Force another layout (first is setContainers) since config has changed + this.layout(new Dimension(this.terminalContainer.offsetWidth, this.terminalContainer.offsetHeight)); return TPromise.as(void 0); } diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index fcfc0a8f8a0..5c91bb1ff06 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -143,11 +143,11 @@ export class TerminalService implements ITerminalService { } public setContainers(panelContainer: Builder, terminalContainer: HTMLElement): void { + this._configHelper.panelContainer = panelContainer; this.terminalContainer = terminalContainer; this._terminalInstances.forEach(terminalInstance => { terminalInstance.attachToElement(this.terminalContainer); }); - this._configHelper.panelContainer = panelContainer; } public showPanel(focus?: boolean): TPromise { @@ -155,7 +155,6 @@ export class TerminalService implements ITerminalService { let panel = this.panelService.getActivePanel(); if (!panel || panel.getId() !== TERMINAL_PANEL_ID) { return this.panelService.openPanel(TERMINAL_PANEL_ID, focus).then(() => { - panel = this.panelService.getActivePanel(); if (focus) { this.getActiveInstance().focus(true); } From 2b5a956ca23448d60cf4858218ae1a489391bbbc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 13 Sep 2016 15:05:02 -0700 Subject: [PATCH 06/23] Fix NPE in terminal code --- .../terminal/electron-browser/terminalInstance.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index 56365a184f0..47e7ac5cc06 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -216,9 +216,9 @@ export class TerminalInstance implements ITerminalInstance { return typeof data === 'string' ? data.replace(TerminalInstance.EOL_REGEX, os.EOL) : data; } - private createProcess(workspace: IWorkspace, name?: string, shell?: IShell) { + private createProcess(workspace: IWorkspace, name: string, shell: IShell) { let locale = this.configHelper.isSetLocaleVariables() ? platform.locale : undefined; - if (!shell) { + if (!shell.executable) { shell = this.configHelper.getShell(); } let env = TerminalInstance.createTerminalEnv(process.env, shell, workspace, locale); @@ -252,9 +252,11 @@ export class TerminalInstance implements ITerminalInstance { let env = TerminalInstance.cloneEnv(parentEnv); env['PTYPID'] = process.pid.toString(); env['PTYSHELL'] = shell.executable; - shell.args.forEach((arg, i) => { - env[`PTYSHELLARG${i}`] = arg; - }); + if (shell.args) { + shell.args.forEach((arg, i) => { + env[`PTYSHELLARG${i}`] = arg; + }); + } env['PTYCWD'] = TerminalInstance.sanitizeCwd(workspace ? workspace.resource.fsPath : os.homedir()); if (locale) { env['LANG'] = TerminalInstance.getLangEnvVariable(locale); From d84fda67886b5db94837e59a9459057a227f329b Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 14 Sep 2016 00:36:18 +0200 Subject: [PATCH 07/23] first cut of supporting PowerShell in integrated terminal --- .../debug/electron-browser/rawDebugSession.ts | 6 +- .../debug/electron-browser/terminalSupport.ts | 65 +++++++++++++------ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts index 1c19f36b60e..1786d1e0a9e 100644 --- a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts @@ -25,6 +25,7 @@ import v8 = require('vs/workbench/parts/debug/node/v8Protocol'); import {IOutputService} from 'vs/workbench/parts/output/common/output'; import {ExtensionsChannelId} from 'vs/platform/extensionManagement/common/extensionManagement'; import {TerminalSupport} from 'vs/workbench/parts/debug/electron-browser/terminalSupport'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {shell} from 'electron'; @@ -75,7 +76,8 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes @ITelemetryService private telemetryService: ITelemetryService, @IOutputService private outputService: IOutputService, @ITerminalService private terminalService: ITerminalService, - @IExternalTerminalService private nativeTerminalService: IExternalTerminalService + @IExternalTerminalService private nativeTerminalService: IExternalTerminalService, + @IConfigurationService private configurationService: IConfigurationService ) { super(); this.emittedStopped = false; @@ -348,7 +350,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes if (request.command === 'runInTerminal') { - TerminalSupport.runInTerminal(this.terminalService, this.nativeTerminalService, request.arguments, response).then(() => { + TerminalSupport.runInTerminal(this.terminalService, this.nativeTerminalService, this.configurationService, request.arguments, response).then(() => { this.sendResponse(response); }, e => { response.success = false; diff --git a/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts b/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts index 0abf4baf819..b8474a0018f 100644 --- a/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts +++ b/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts @@ -8,33 +8,40 @@ import platform = require('vs/base/common/platform'); import {TPromise} from 'vs/base/common/winjs.base'; import {ITerminalService, ITerminalInstance} from 'vs/workbench/parts/terminal/electron-browser/terminal'; import {ITerminalService as IExternalTerminalService} from 'vs/workbench/parts/execution/common/execution'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +export interface IIntegratedTerminalConfiguration { + terminal: { + integrated: { + shell: { + windows: string + } + } + }; +} + export class TerminalSupport { private static integratedTerminalInstance: ITerminalInstance; - public static runInTerminal(terminalService: ITerminalService, nativeTerminalService: IExternalTerminalService, args: DebugProtocol.RunInTerminalRequestArguments, response: DebugProtocol.RunInTerminalResponse): TPromise { + public static runInTerminal(terminalService: ITerminalService, nativeTerminalService: IExternalTerminalService, configurationService: IConfigurationService, args: DebugProtocol.RunInTerminalRequestArguments, response: DebugProtocol.RunInTerminalResponse): TPromise { if (args.kind === 'external') { return nativeTerminalService.runInTerminal(args.title, args.cwd, args.args, args.env); } - return this.runInIntegratedTerminal(terminalService, args); - } - - private static runInIntegratedTerminal(terminalService: ITerminalService, args: DebugProtocol.RunInTerminalRequestArguments): TPromise { if (!TerminalSupport.integratedTerminalInstance) { TerminalSupport.integratedTerminalInstance = terminalService.createInstance(args.title || nls.localize('debuggee', "debuggee")); } terminalService.setActiveInstance(TerminalSupport.integratedTerminalInstance); terminalService.showPanel(true); - const command = this.prepareCommand(args); + const command = this.prepareCommand(args, configurationService); TerminalSupport.integratedTerminalInstance.sendText(command, true); return TPromise.as(void 0); } - private static prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments): string { + private static prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments, configurationService: IConfigurationService): string { let command = ''; if (platform.isWindows) { @@ -44,21 +51,41 @@ export class TerminalSupport { return (s.indexOf(' ') >= 0 || s.indexOf('"') >= 0) ? `"${s}"` : s; }; - if (args.cwd) { - command += `cd ${quote(args.cwd)} && `; + const conf = configurationService.getConfiguration(); + + let isPowerShell = false; + if (conf.terminal && conf.terminal.integrated && conf.terminal.integrated.shell && conf.terminal.integrated.shell.windows) { + isPowerShell = conf.terminal.integrated.shell.windows.indexOf('PowerShell') >= 0; } - if (args.env) { - command += 'cmd /C "'; - for (let key in args.env) { - command += `set "${key}=${args.env[key]}" && `; + + if (isPowerShell) { + + if (args.cwd) { + command += `cd ${quote(args.cwd)}; `; + } + for (let a of args.args) { + command += `${quote(a)} `; + } + + } else { + + if (args.cwd) { + command += `cd ${quote(args.cwd)} && `; + } + if (args.env) { + command += 'cmd /C "'; + for (let key in args.env) { + command += `set "${key}=${args.env[key]}" && `; + } + } + for (let a of args.args) { + command += `${quote(a)} `; + } + if (args.env) { + command += '"'; } } - for (let a of args.args) { - command += `${quote(a)} `; - } - if (args.env) { - command += '"'; - } + } else { const quote = (s: string) => { s = s.replace(/\"/g, '\\"'); From 41e7baad7019d6147987767b29b64fca01804cbd Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 14 Sep 2016 00:39:25 +0200 Subject: [PATCH 08/23] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 336a0c85e76..5aebf4f06cc 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "d643199/node-debug.zip", + "zip": "85ec7d8/node-debug.zip", "output": "" } From 1e51cd3d369c285eca34887f265c3e7499f10176 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 13 Sep 2016 16:05:35 -0700 Subject: [PATCH 09/23] Add shellArgs to API docs Part of #10917 --- src/vs/vscode.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 024de4ba099..6ac61419bc9 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3498,6 +3498,7 @@ declare namespace vscode { * * @param name Optional human-readable string which will be used to represent the terminal in the UI. * @param shellPath Optional path to a custom shell executable to be used in the terminal. + * @param shellArgs Optional args for the custom shell executable, this does not work on Windows (see #8429) * @return A new Terminal. */ export function createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): Terminal; From 5a5a9f7a40c93a6a7797b3553e8997b0d488589b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 13 Sep 2016 16:15:54 -0700 Subject: [PATCH 10/23] Reintroduce terminal API request queue system Fixes #11990 --- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- .../api/node/extHostTerminalService.ts | 46 +++++++++++++++---- .../api/node/mainThreadTerminalService.ts | 5 +- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 2b0c5345d70..1e10df02db2 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -153,7 +153,7 @@ export abstract class MainThreadOutputServiceShape { } export abstract class MainThreadTerminalServiceShape { - $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): number { throw ni(); } + $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): TPromise { throw ni(); } $dispose(terminalId: number): void { throw ni(); } $hide(terminalId: number): void { throw ni(); } $sendText(terminalId: number, text: string, addNewLine: boolean): void { throw ni(); } diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 04032aea8b3..2253748554b 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -10,16 +10,21 @@ import {MainContext, MainThreadTerminalServiceShape} from './extHost.protocol'; export class ExtHostTerminal implements vscode.Terminal { - public _name: string; - + private _name: string; private _id: number; private _proxy: MainThreadTerminalServiceShape; private _disposed: boolean; + private _queuedRequests: ApiRequest[] = []; - constructor(proxy: MainThreadTerminalServiceShape, id: number, name?: string, shellPath?: string, shellArgs?: string[]) { + constructor(proxy: MainThreadTerminalServiceShape, name?: string, shellPath?: string, shellArgs?: string[]) { this._name = name; this._proxy = proxy; - this._id = this._proxy.$createTerminal(name, shellPath, shellArgs); + this._proxy.$createTerminal(name, shellPath, shellArgs).then((id) => { + this._id = id; + this._queuedRequests.forEach((r) => { + r.run(this._proxy, this._id); + }); + }); } public get name(): string { @@ -29,26 +34,35 @@ export class ExtHostTerminal implements vscode.Terminal { public sendText(text: string, addNewLine: boolean = true): void { this._checkDisposed(); - this._proxy.$sendText(this._id, text, addNewLine); + this._queueApiRequest(this._proxy.$sendText, [text, addNewLine]); } public show(preserveFocus: boolean): void { this._checkDisposed(); - this._proxy.$show(this._id, preserveFocus); + this._queueApiRequest(this._proxy.$show, [preserveFocus]); } public hide(): void { this._checkDisposed(); - this._proxy.$hide(this._id); + this._queueApiRequest(this._proxy.$hide, []); } public dispose(): void { if (!this._disposed) { this._disposed = true; - this._proxy.$dispose(this._id); + this._queueApiRequest(this._proxy.$dispose, []); } } + private _queueApiRequest(callback: (...args: any[]) => void, args: any[]) { + let request: ApiRequest = new ApiRequest(callback, args); + if (!this._id) { + this._queuedRequests.push(request); + return; + } + request.run(this._proxy, this._id); + } + private _checkDisposed() { if (this._disposed) { throw new Error('Terminal has already been disposed'); @@ -65,6 +79,20 @@ export class ExtHostTerminalService { } public createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { - return new ExtHostTerminal(this._proxy, -1, name, shellPath, shellArgs); + return new ExtHostTerminal(this._proxy, name, shellPath, shellArgs); } } + +class ApiRequest { + private _callback: (...args: any[]) => void; + private _args: any[]; + + constructor(callback: (...args: any[]) => void, args: any[]) { + this._callback = callback; + this._args = args; + } + + public run(proxy: MainThreadTerminalServiceShape, id: number) { + this._callback.apply(proxy, [id].concat(this._args)); + } +} \ No newline at end of file diff --git a/src/vs/workbench/api/node/mainThreadTerminalService.ts b/src/vs/workbench/api/node/mainThreadTerminalService.ts index 67c0c1bd8fe..6c9a57262ab 100644 --- a/src/vs/workbench/api/node/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/node/mainThreadTerminalService.ts @@ -8,6 +8,7 @@ import {ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/ter import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {IPartService} from 'vs/workbench/services/part/common/partService'; import {MainThreadTerminalServiceShape} from './extHost.protocol'; +import {TPromise} from 'vs/base/common/winjs.base'; export class MainThreadTerminalService extends MainThreadTerminalServiceShape { @@ -19,8 +20,8 @@ export class MainThreadTerminalService extends MainThreadTerminalServiceShape { super(); } - public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): number { - return this.terminalService.createInstance(name, shellPath, shellArgs).id; + public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): TPromise { + return TPromise.as(this.terminalService.createInstance(name, shellPath, shellArgs).id); } public $show(terminalId: number, preserveFocus: boolean): void { From 6fa85223efb25ad7ce3e534c7eb07edd9524bd6d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Sep 2016 07:29:20 +0200 Subject: [PATCH 11/23] Electron Update 1.x (#11157) * use electron 1.3.4 * ATOM_SHELL_INTERNAL_RUN_AS_NODE => ELECTRON_RUN_AS_NODE * OSS input * update electron.d.ts * workaround for #8708 * bump oniguruma and chokidar with custom fsevents * build with appveyor config from master * oops, still use ELECTRON_RUN_AS_NODE * use electron 1.3.5 * optional fsevents * add cat.exe to workaround output issues * use cat for tests * remove some now obsolete ELECTRON_NO_ATTACH_CONSOLE * also pipe output to cat for code.sh on windows * unset ELECTRON_RUN_AS_NODE for appveyor * fix tfs builds? * fix build * fix build? * use cat only when running tests locally --- OSSREADME.json | 8 +- appveyor.yml | 2 +- build/gulpfile.vscode.js | 1 + extensions/typescript/src/utils/electron.ts | 2 +- .../typescript/src/utils/electronForkStart.ts | 4 +- npm-shrinkwrap.json | 2 +- package.json | 2 +- resources/darwin/bin/code.sh | 2 +- resources/linux/bin/code.sh | 2 +- resources/win32/bin/cat.exe | Bin 0 -> 10240 bytes resources/win32/bin/code.cmd | 4 +- resources/win32/bin/code.sh | 2 +- scripts/code-cli.sh | 2 +- scripts/test-integration.bat | 4 +- scripts/test.bat | 22 +- scripts/test.sh | 4 +- src/typings/electron.d.ts | 701 ++++++++++++++---- src/vs/base/node/stdFork.ts | 2 +- src/vs/base/node/stdForkStart.js | 4 +- src/vs/code/electron-main/main.ts | 8 +- src/vs/code/electron-main/window.ts | 2 +- src/vs/code/node/cli.ts | 2 +- .../viewParts/lineNumbers/lineNumbers.css | 5 +- .../debug/electron-browser/debugService.ts | 2 +- .../electron-browser/electronGitService.ts | 2 +- .../electron-browser/terminalProcess.js | 2 +- .../electron-browser/contextmenuService.ts | 2 +- 27 files changed, 623 insertions(+), 172 deletions(-) create mode 100644 resources/win32/bin/cat.exe diff --git a/OSSREADME.json b/OSSREADME.json index 5fe88517ee4..1c3d9cb2135 100644 --- a/OSSREADME.json +++ b/OSSREADME.json @@ -38,7 +38,7 @@ }, { "name": "chromium", - "version": "49.0.2623.75", + "version": "52.0.2743.82", "repositoryURL": "http://www.chromium.org/Home", "licenseDetail": [ "BSD License", @@ -74,20 +74,20 @@ }, { "name": "libchromiumcontent", - "version": "49.0.2623.75", + "version": "52.0.2743.82", "license": "MIT", "repositoryURL": "https://github.com/electron/libchromiumcontent", "isProd": true }, { "name": "nodejs", - "version": "5.10.0", + "version": "6.3.0", "repositoryURL": "https://github.com/nodejs/node", "isProd": true }, { "name": "electron", - "version": "0.37.6", + "version": "1.3.5", "license": "MIT", "repositoryURL": "https://github.com/electron/electron", "isProd": true diff --git a/appveyor.yml b/appveyor.yml index 67d80cae24f..3632e51d974 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ environment: - ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1 + ELECTRON_RUN_AS_NODE: 1 VSCODE_BUILD_VERBOSE: true install: diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 8df4cf8257b..1b6fda4d1de 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -230,6 +230,7 @@ function packageTask(platform, arch, opts) { if (platform === 'win32') { result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32' })); + result = es.merge(result, gulp.src('resources/win32/bin/cat.exe', { base: 'resources/win32' })); result = es.merge(result, gulp.src('resources/win32/bin/code.cmd', { base: 'resources/win32' }) .pipe(replace('@@NAME@@', product.nameShort)) diff --git a/extensions/typescript/src/utils/electron.ts b/extensions/typescript/src/utils/electron.ts index a4e08453f9f..c0bda301689 100644 --- a/extensions/typescript/src/utils/electron.ts +++ b/extensions/typescript/src/utils/electron.ts @@ -48,7 +48,7 @@ function generatePatchedEnv(env:any, stdInPipeName:string, stdOutPipeName:string newEnv['STDIN_PIPE_NAME'] = stdInPipeName; newEnv['STDOUT_PIPE_NAME'] = stdOutPipeName; newEnv['STDERR_PIPE_NAME'] = stdErrPipeName; - newEnv['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = '1'; + newEnv['ELECTRON_RUN_AS_NODE'] = '1'; return newEnv; } diff --git a/extensions/typescript/src/utils/electronForkStart.ts b/extensions/typescript/src/utils/electronForkStart.ts index 46a12506041..83f75724002 100644 --- a/extensions/typescript/src/utils/electronForkStart.ts +++ b/extensions/typescript/src/utils/electronForkStart.ts @@ -31,7 +31,7 @@ var stdErrPipeName = process.env['STDERR_PIPE_NAME']; log('STDIN_PIPE_NAME: ' + stdInPipeName); log('STDOUT_PIPE_NAME: ' + stdOutPipeName); log('STDERR_PIPE_NAME: ' + stdErrPipeName); -log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']); +log('ELECTRON_RUN_AS_NODE: ' + process.env['ELECTRON_RUN_AS_NODE']); // stdout redirection to named pipe (function() { @@ -147,7 +147,7 @@ log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_A delete process.env['STDIN_PIPE_NAME']; delete process.env['STDOUT_PIPE_NAME']; delete process.env['STDERR_PIPE_NAME']; - delete process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete process.env['ELECTRON_RUN_AS_NODE']; require(program); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 4266bd833e9..743ef15228f 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -414,7 +414,7 @@ "from": "vscode-textmate@2.1.1", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-2.1.1.tgz" }, - "windows-mutex": { + "windows-mutex": { "version": "0.2.0", "from": "windows-mutex@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/windows-mutex/-/windows-mutex-0.2.0.tgz" diff --git a/package.json b/package.json index 224945b0df9..75cfedab218 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.6.0", - "electronVersion": "0.37.6", + "electronVersion": "1.3.5", "distro": "3d44b35db8d394d6d7b2bc224675735a0a8f2704", "author": { "name": "Microsoft Corporation" diff --git a/resources/darwin/bin/code.sh b/resources/darwin/bin/code.sh index ac498810000..9dba3f8e378 100755 --- a/resources/darwin/bin/code.sh +++ b/resources/darwin/bin/code.sh @@ -7,5 +7,5 @@ function realpath() { /usr/bin/python -c "import os,sys; print os.path.realpath( CONTENTS="$(dirname "$(dirname "$(dirname "$(dirname "$(realpath "$0")")")")")" ELECTRON="$CONTENTS/MacOS/Electron" CLI="$CONTENTS/Resources/app/out/cli.js" -ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" exit $? \ No newline at end of file diff --git a/resources/linux/bin/code.sh b/resources/linux/bin/code.sh index 77fa49722f7..f0877aa4c9f 100755 --- a/resources/linux/bin/code.sh +++ b/resources/linux/bin/code.sh @@ -33,5 +33,5 @@ fi ELECTRON="$VSCODE_PATH/@@NAME@@" CLI="$VSCODE_PATH/resources/app/out/cli.js" -ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" exit $? \ No newline at end of file diff --git a/resources/win32/bin/cat.exe b/resources/win32/bin/cat.exe new file mode 100644 index 0000000000000000000000000000000000000000..5fcc054e438938165161ede4e41d89202c797df0 GIT binary patch literal 10240 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 vH@xKJ&oAiGJnG*cv literal 0 HcmV?d00001 diff --git a/resources/win32/bin/code.cmd b/resources/win32/bin/code.cmd index a975610eb31..2564a3234ba 100644 --- a/resources/win32/bin/code.cmd +++ b/resources/win32/bin/code.cmd @@ -1,6 +1,6 @@ @echo off setlocal set VSCODE_DEV= -set ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 -call "%~dp0..\@@NAME@@.exe" "%~dp0..\resources\\app\\out\\cli.js" %* +set ELECTRON_RUN_AS_NODE=1 +call "%~dp0..\@@NAME@@.exe" "%~dp0..\resources\\app\\out\\cli.js" %* | cat endlocal \ No newline at end of file diff --git a/resources/win32/bin/code.sh b/resources/win32/bin/code.sh index 83f7bfea10c..49636eec1e2 100644 --- a/resources/win32/bin/code.sh +++ b/resources/win32/bin/code.sh @@ -11,5 +11,5 @@ if [ "$(expr substr $(uname -s) 1 9)" == "CYGWIN_NT" ]; then else CLI="$VSCODE_PATH/resources/app/out/cli.js" fi -ELECTRON_NO_ATTACH_CONSOLE=1 ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" | cat exit $? diff --git a/scripts/code-cli.sh b/scripts/code-cli.sh index 5823276e47f..9a4c03e31d4 100755 --- a/scripts/code-cli.sh +++ b/scripts/code-cli.sh @@ -30,7 +30,7 @@ function code() { CLI="$ROOT/out/cli.js" - ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ + ELECTRON_RUN_AS_NODE=1 \ NODE_ENV=development \ VSCODE_DEV=1 \ ELECTRON_ENABLE_LOGGING=1 \ diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index 87dec89d1a1..16a617b5e11 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -1,10 +1,8 @@ @echo off setlocal -rem APPVEYOR Builds if not "%APPVEYOR%" == "" ( - set ELECTRON_NO_ATTACH_CONSOLE=1 - set ATOM_SHELL_INTERNAL_RUN_AS_NODE= + set ELECTRON_RUN_AS_NODE= ) :: Integration Tests diff --git a/scripts/test.bat b/scripts/test.bat index e55af32e6c0..bd7a7fe82cb 100644 --- a/scripts/test.bat +++ b/scripts/test.bat @@ -1,17 +1,7 @@ @echo off setlocal -set ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 - -rem TFS Builds -if not "%BUILD_BUILDID%" == "" ( - set ELECTRON_NO_ATTACH_CONSOLE=1 -) - -rem APPVEYOR Builds -if not "%APPVEYOR%" == "" ( - set ELECTRON_NO_ATTACH_CONSOLE=1 -) +set ELECTRON_RUN_AS_NODE=1 pushd %~dp0\.. @@ -20,7 +10,15 @@ set NAMESHORT=%NAMESHORT: "=% set NAMESHORT=%NAMESHORT:"=%.exe set CODE=".build\electron\%NAMESHORT%" -%CODE% .\node_modules\mocha\bin\_mocha %* +rem TFS Builds +if not "%BUILD_BUILDID%" == "" ( + %CODE% .\node_modules\mocha\bin\_mocha %* +) + +rem Otherwise +if "%BUILD_BUILDID%" == "" ( + %CODE% .\node_modules\mocha\bin\_mocha %* | .\resources\win32\bin\cat +) popd endlocal diff --git a/scripts/test.sh b/scripts/test.sh index 5b6a7d2e39d..59bd5615b52 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -30,11 +30,11 @@ test -d out || ./node_modules/.bin/gulp compile # Unit Tests export VSCODE_DEV=1 if [[ "$OSTYPE" == "darwin"* ]]; then - cd $ROOT ; ulimit -n 4096 ; ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ + cd $ROOT ; ulimit -n 4096 ; ELECTRON_RUN_AS_NODE=1 \ "$CODE" \ node_modules/mocha/bin/_mocha "$@" else - cd $ROOT ; ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ + cd $ROOT ; ELECTRON_RUN_AS_NODE=1 \ "$CODE" \ node_modules/mocha/bin/_mocha "$@" fi diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index 938d88df290..cf4ce357304 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Electron v1.2.5 +// Type definitions for Electron v1.3.4 // Project: http://electron.atom.io/ // Definitions by: jedmao , rhysd , Milan Burda // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -25,6 +25,23 @@ declare namespace Electron { sender: EventEmitter; } + type Point = { + x: number; + y: number; + } + + type Size = { + width: number; + height: number; + } + + type Rectangle = { + x: number; + y: number; + width: number; + height: number; + } + // https://github.com/electron/electron/blob/master/docs/api/app.md /** @@ -160,6 +177,12 @@ declare namespace Electron { * Emitted when the gpu process crashes. */ on(event: 'gpu-process-crashed', listener: Function): this; + /** + * Emitted when Chrome's accessibility support changes. + * + * Note: This API is only available on macOS and Windows. + */ + on(event: 'accessibility-support-changed', listener: (event: Event, accessibilitySupportEnabled: boolean) => void): this; on(event: string, listener: Function): this; /** * Try to close all windows. The before-quit event will first be emitted. @@ -273,28 +296,43 @@ declare namespace Electron { * Once registered, all links with your-protocol:// will be opened with the current executable. * The whole link, including protocol, will be passed to your application as a parameter. * + * On Windows you can provide optional parameters path, the path to your executable, + * and args, an array of arguments to be passed to your executable when it launches. + * + * @param protocol The name of your protocol, without ://. + * @param path Defaults to process.execPath. + * @param args Defaults to an empty array. + * * Note: This is only implemented on macOS and Windows. * On macOS, you can only register protocols that have been added to your app's info.plist. */ - setAsDefaultProtocolClient(protocol: string): void; + setAsDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** * Removes the current executable as the default handler for a protocol (aka URI scheme). * + * @param protocol The name of your protocol, without ://. + * @param path Defaults to process.execPath. + * @param args Defaults to an empty array. + * * Note: This is only implemented on macOS and Windows. */ - removeAsDefaultProtocolClient(protocol: string): void; + removeAsDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** + * @param protocol The name of your protocol, without ://. + * @param path Defaults to process.execPath. + * @param args Defaults to an empty array. + * * @returns Whether the current executable is the default handler for a protocol (aka URI scheme). * * Note: This is only implemented on macOS and Windows. */ - isDefaultProtocolClient(protocol: string): boolean; + isDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** * Adds tasks to the Tasks category of JumpList on Windows. * * Note: This API is only available on Windows. */ - setUserTasks(tasks: Task[]): void; + setUserTasks(tasks: Task[]): boolean; /** * This method makes your application a Single Instance Application instead of allowing * multiple instances of your app to run, this will ensure that only a single instance @@ -326,6 +364,8 @@ declare namespace Electron { getCurrentActivityType(): string; /** * Changes the Application User Model ID to id. + * + * Note: This is only implemented on Windows. */ setAppUserModelId(id: string): void; /** @@ -341,6 +381,33 @@ declare namespace Electron { * This method can only be called before app is ready. */ disableHardwareAcceleration(): void; + /** + * @returns whether current desktop environment is Unity launcher. (Linux) + * + * Note: This API is only available on Linux. + */ + isUnityRunning(): boolean; + /** + * Returns a Boolean, true if Chrome's accessibility support is enabled, false otherwise. + * This API will return true if the use of assistive technologies, such as screen readers, + * has been detected. + * See https://www.chromium.org/developers/design-documents/accessibility for more details. + * + * Note: This API is only available on macOS and Windows. + */ + isAccessibilitySupportEnabled(): boolean; + /** + * @returns an Object with the login item settings of the app. + * + * Note: This API is only available on macOS and Windows. + */ + getLoginItemSettings(): LoginItemSettings; + /** + * Set the app's login item settings. + * + * Note: This API is only available on macOS and Windows. + */ + setLoginItemSettings(settings: LoginItemSettings): void; commandLine: CommandLine; /** * Note: This API is only available on macOS. @@ -348,7 +415,7 @@ declare namespace Electron { dock: Dock; } - type AppPathName = 'home' | 'appData' | 'userData' | 'temp' | 'exe' | 'module' | 'desktop' | 'documents' | 'downloads' | 'music' | 'pictures' | 'videos' | 'pepperFlashSystemPlugin'; + type AppPathName = 'home'|'appData'|'userData'|'temp'|'exe'|'module'|'desktop'|'documents'|'downloads'|'music'|'pictures'|'videos'|'pepperFlashSystemPlugin'; interface ImportCertificateOptions { /** @@ -368,7 +435,7 @@ declare namespace Electron { * Note: This will not affect process.argv, and is mainly used by developers * to control some low-level Chromium behaviors. */ - appendSwitch(_switch: string, value?: string | number): void; + appendSwitch(_switch: string, value?: string): void; /** * Append an argument to Chromium's command line. The argument will quoted properly. * @@ -414,6 +481,20 @@ declare namespace Electron { * Note: This API is only available on macOS. */ getBadge(): string; + /** + * Sets the counter badge for current app. Setting the count to 0 will hide the badge. + * + * @returns True when the call succeeded, otherwise returns false. + * + * Note: This API is only available on macOS and Linux. + */ + setBadgeCount(count: number): boolean; + /** + * @returns The current value displayed in the counter badge. + * + * Note: This API is only available on macOS and Linux. + */ + getBadgeCount(): number; /** * Hides the dock icon. * @@ -426,6 +507,13 @@ declare namespace Electron { * Note: This API is only available on macOS. */ show(): void; + /** + * @returns Whether the dock icon is visible. + * The app.dock.show() call is asynchronous so this method might not return true immediately after that call. + * + * Note: This API is only available on macOS. + */ + isVisible(): boolean; /** * Sets the application dock menu. * @@ -472,6 +560,32 @@ declare namespace Electron { iconIndex?: number; } + interface LoginItemSettings { + /** + * True if the app is set to open at login. + */ + openAtLogin: boolean; + /** + * True if the app is set to open as hidden at login. This setting is only supported on macOS. + */ + openAsHidden: boolean; + /** + * True if the app was opened at login automatically. This setting is only supported on macOS. + */ + wasOpenedAtLogin?: boolean; + /** + * True if the app was opened as a hidden login item. This indicates that the app should not + * open any windows at startup. This setting is only supported on macOS. + */ + wasOpenedAsHidden?: boolean; + /** + * True if the app was opened as a login item that should restore the state from the previous session. + * This indicates that the app should restore the windows that were open the last time the app was closed. + * This setting is only supported on macOS. + */ + restoreState?: boolean; + } + // https://github.com/electron/electron/blob/master/docs/api/auto-updater.md /** @@ -504,6 +618,10 @@ declare namespace Electron { * Set the url and initialize the auto updater. */ setFeedURL(url: string, requestHeaders?: Headers): void; + /** + * @returns The current update feed URL. + */ + getFeedURL(): string; /** * Ask the server whether there is an update, you have to call setFeedURL * before using this API @@ -527,7 +645,7 @@ declare namespace Electron { * Emitted when the document changed its title, * calling event.preventDefault() would prevent the native window’s title to change. */ - on(event: 'page-title-updated', listener: (event: Event) => void): this; + on(event: 'page-title-updated', listener: (event: Event, title: string) => void): this; /** * Emitted when the window is going to be closed. It’s emitted before the beforeunload * and unload event of the DOM. Calling event.preventDefault() will cancel the close. @@ -629,6 +747,9 @@ declare namespace Electron { */ on(event: 'swipe', listener: (event: Event, direction: SwipeDirection) => void): this; on(event: string, listener: Function): this; + /** + * Creates a new BrowserWindow with native properties as set by the options. + */ constructor(options?: BrowserWindowOptions); /** * @returns All opened browser windows. @@ -703,6 +824,10 @@ declare namespace Electron { * @returns Whether the window is focused. */ isFocused(): boolean; + /** + * @returns Whether the window is destroyed. + */ + isDestroyed(): boolean; /** * Shows and gives focus to the window. */ @@ -764,7 +889,7 @@ declare namespace Electron { * * Note: This API is available only on macOS. */ - setAspectRatio(aspectRatio: number, extraSize?: Dimension): void; + setAspectRatio(aspectRatio: number, extraSize?: Size): void; /** * Resizes and moves the window to width, height, x, y. */ @@ -773,6 +898,14 @@ declare namespace Electron { * @returns The window's width, height, x and y values. */ getBounds(): Rectangle; + /** + * Resizes and moves the window's client area (e.g. the web page) to width, height, x, y. + */ + setContentBounds(options: Rectangle, animate?: boolean): void; + /** + * @returns The window's client area (e.g. the web page) width, height, x and y values. + */ + getContentBounds(): Rectangle; /** * Resizes the window to width and height. */ @@ -968,6 +1101,13 @@ declare namespace Electron { * @param callback Supplies the image that stores data of the snapshot. */ capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; + /** + * Captures the snapshot of page within rect, upon completion the callback + * will be called. Omitting the rect would capture the whole visible page. + * Note: Be sure to read documents on remote buffer in remote if you are going + * to use this API in renderer process. + * @param callback Supplies the image that stores data of the snapshot. + */ capturePage(callback: (image: NativeImage) => void): void; /** * Same as webContents.loadURL(url). @@ -990,7 +1130,13 @@ declare namespace Electron { * @param progress Valid range is [0, 1.0]. If < 0, the progress bar is removed. * If greater than 0, it becomes indeterminate. */ - setProgressBar(progress: number): void; + setProgressBar(progress: number, options?: { + /** + * Mode for the progress bar. + * Note: This is only implemented on Windows. + */ + mode: 'none' | 'normal' | 'indeterminate' | 'error' | 'paused' + }): void; /** * Sets a 16px overlay onto the current Taskbar icon, usually used to convey * some sort of application status or to passively notify the user. @@ -1014,8 +1160,23 @@ declare namespace Electron { * Add a thumbnail toolbar with a specified set of buttons to the thumbnail image * of a window in a taskbar button layout. * @returns Whether the thumbnail has been added successfully. + * + * Note: This API is available only on Windows. */ setThumbarButtons(buttons: ThumbarButton[]): boolean; + /** + * Sets the region of the window to show as the thumbnail image displayed when hovering + * over the window in the taskbar. You can reset the thumbnail to be the entire window + * by specifying an empty region: {x: 0, y: 0, width: 0, height: 0}. + * + * Note: This API is available only on Windows. + */ + setThumbnailClip(region: Rectangle): boolean; + /** + * Sets the toolTip that is displayed when hovering over the window thumbnail in the taskbar. + * Note: This API is available only on Windows. + */ + setThumbnailToolTip(toolTip: string): boolean; /** * Same as webContents.showDefinitionForSelection(). * Note: This API is available only on macOS. @@ -1258,12 +1419,17 @@ declare namespace Electron { defaultEncoding?: string; /** * Whether to throttle animations and timers when the page becomes background. - * Default: true + * Default: true. */ backgroundThrottling?: boolean; + /** + * Whether to enable offscreen rendering for the browser window. + * Default: false. + */ + offscreen?: boolean; } - interface BrowserWindowOptions extends Rectangle { + interface BrowserWindowOptions { /** * Window’s width in pixels. * Default: 800. @@ -1387,7 +1553,7 @@ declare namespace Electron { /** * The window icon, when omitted on Windows the executable’s icon would be used as window icon. */ - icon?: NativeImage | string; + icon?: NativeImage|string; /** * Whether window should be shown when created. * Default: true. @@ -1458,22 +1624,20 @@ declare namespace Electron { * The style of window title bar. */ titleBarStyle?: 'default' | 'hidden' | 'hidden-inset'; + /** + * Use WS_THICKFRAME style for frameless windows on Windows + */ + thickFrame?: boolean; /** * Settings of web page’s features. */ webPreferences?: WebPreferences; } - type BrowserWindowType = BrowserWindowTypeLinux | BrowserWindowTypeMac; + type BrowserWindowType = BrowserWindowTypeLinux | BrowserWindowTypeMac | BrowserWindowTypeWindows; type BrowserWindowTypeLinux = 'desktop' | 'dock' | 'toolbar' | 'splash' | 'notification'; type BrowserWindowTypeMac = 'desktop' | 'textured'; - - interface Rectangle { - x?: number; - y?: number; - width?: number; - height?: number; - } + type BrowserWindowTypeWindows = 'toolbar'; // https://github.com/electron/electron/blob/master/docs/api/clipboard.md @@ -1541,10 +1705,27 @@ declare namespace Electron { html?: string; image?: NativeImage; }, type?: ClipboardType): void; + /** + * @returns An Object containing title and url keys representing the bookmark in the clipboard. + * + * Note: This API is available on macOS and Windows. + */ + readBookmark(): Bookmark; + /** + * Writes the title and url into the clipboard as a bookmark. + * + * Note: This API is available on macOS and Windows. + */ + writeBookmark(title: string, url: string, type?: ClipboardType): void; } type ClipboardType = '' | 'selection'; + interface Bookmark { + title: string; + url: string; + } + // https://github.com/electron/electron/blob/master/docs/api/content-tracing.md /** @@ -1701,7 +1882,7 @@ declare namespace Electron { * An object you can define that will be sent along with the report. * Only string properties are sent correctly, nested objects are not supported. */ - extra?: { [prop: string]: string }; + extra?: {[prop: string]: string}; } interface CrashReport { @@ -1734,7 +1915,7 @@ declare namespace Electron { * The suggested size that thumbnail should be scaled. * Default: {width: 150, height: 150} */ - thumbnailSize?: Dimension; + thumbnailSize?: Size; } interface DesktopCapturerSource { @@ -1836,7 +2017,7 @@ declare namespace Electron { /** * Contains which features the dialog should use. */ - properties?: ('openFile' | 'openDirectory' | 'multiSelections' | 'createDirectory')[]; + properties?: ('openFile' | 'openDirectory' | 'multiSelections' | 'createDirectory' | 'showHiddenFiles')[]; } interface SaveDialogOptions { @@ -1920,6 +2101,11 @@ declare namespace Electron { * routine to determine the save path (Usually prompts a save dialog). */ setSavePath(path: string): void; + /** + * @returns The save path of the download item. + * This will be either the path set via downloadItem.setSavePath(path) or the path selected from the shown save dialog. + */ + getSavePath(): string; /** * Pauses the download. */ @@ -2125,8 +2311,8 @@ declare namespace Electron { } type MenuItemType = 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'; - type MenuItemRole = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteandmatchstyle' | 'selectall' | 'delete' | 'minimize' | 'close' | 'quit' | 'togglefullscreen'; - type MenuItemRoleMac = 'about' | 'hide' | 'hideothers' | 'unhide' | 'front' | 'zoom' | 'window' | 'help' | 'services'; + type MenuItemRole = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteandmatchstyle' | 'selectall' | 'delete' | 'minimize' | 'close' | 'quit' | 'togglefullscreen' | 'resetzoom' | 'zoomin' | 'zoomout'; + type MenuItemRoleMac = 'about' | 'hide' | 'hideothers' | 'unhide' | 'startspeaking' | 'stopspeaking' | 'front' | 'zoom' | 'window' | 'help' | 'services'; interface MenuItemOptions { /** @@ -2192,7 +2378,7 @@ declare namespace Electron { * In Electron for the APIs that take images, you can pass either file paths * or NativeImage instances. When passing null, an empty image will be used. */ - icon?: NativeImage | string; + icon?: NativeImage|string; /** * If false, the menu item will be greyed out and unclickable. */ @@ -2209,7 +2395,7 @@ declare namespace Electron { * Should be specified for submenu type menu item, when it's specified the * type: 'submenu' can be omitted for the menu item */ - submenu?: Menu | MenuItemOptions[]; + submenu?: Menu|MenuItemOptions[]; /** * Unique within a single menu. If defined then it can be used as a reference * to this item by the position attribute. @@ -2270,7 +2456,7 @@ declare namespace Electron { * @param x Horizontal coordinate where the menu will be placed. * @param y Vertical coordinate where the menu will be placed. */ - popup(browserWindow?: BrowserWindow, x?: number, y?: number, select?: number): void; + popup(browserWindow?: BrowserWindow, x?: number, y?: number): void; /** * Appends the menuItem to the menu. */ @@ -2309,13 +2495,25 @@ declare namespace Electron { */ static createFromDataURL(dataURL: string): NativeImage; /** - * @returns Buffer Contains the image's PNG encoded data. + * @returns Buffer that contains the image's PNG encoded data. */ toPNG(): Buffer; /** - * @returns Buffer Contains the image's JPEG encoded data. + * @returns Buffer that contains the image's JPEG encoded data. */ toJPEG(quality: number): Buffer; + /** + * @returns Buffer that contains a copy of the image's raw bitmap pixel data. + */ + toBitmap(): Buffer; + /** + * @returns Buffer that contains the image's raw bitmap pixel data. + * + * The difference between getBitmap() and toBitmap() is, getBitmap() does not copy the bitmap data, + * so you have to use the returned Buffer immediately in current event loop tick, + * otherwise the data might be changed or destroyed. + */ + getBitmap(): Buffer; /** * @returns string The data URL of the image. */ @@ -2333,7 +2531,7 @@ declare namespace Electron { /** * @returns {} The size of the image. */ - getSize(): Dimension; + getSize(): Size; /** * Marks the image as template image. */ @@ -2556,10 +2754,10 @@ declare namespace Electron { * Unique identifier associated with the display. */ id: number; - bounds: Bounds; - workArea: Bounds; - size: Dimension; - workAreaSize: Dimension; + bounds: Rectangle; + workArea: Rectangle; + size: Size; + workAreaSize: Size; /** * Output device’s pixel scale factor. */ @@ -2571,23 +2769,6 @@ declare namespace Electron { touchSupport: 'available' | 'unavailable' | 'unknown'; } - type Bounds = { - x: number; - y: number; - width: number; - height: number; - } - - type Dimension = { - width: number; - height: number; - } - - type Point = { - x: number; - y: number; - } - type DisplayMetrics = 'bounds' | 'workArea' | 'scaleFactor' | 'rotation'; /** @@ -2627,7 +2808,7 @@ declare namespace Electron { /** * @returns The display that most closely intersects the provided bounds. */ - getDisplayMatching(rect: Bounds): Display; + getDisplayMatching(rect: Rectangle): Display; } // https://github.com/electron/electron/blob/master/docs/api/session.md @@ -2641,7 +2822,7 @@ declare namespace Electron { /** * @returns a new Session instance from partition string. */ - static fromPartition(partition: string): Session; + static fromPartition(partition: string, options?: FromPartitionOptions): Session; /** * @returns the default session object of the app. */ @@ -2680,7 +2861,7 @@ declare namespace Electron { /** * Sets the proxy settings. */ - setProxy(config: string, callback: Function): void; + setProxy(config: ProxyConfig, callback: Function): void; /** * Resolves the proxy information for url. */ @@ -2741,6 +2922,13 @@ declare namespace Electron { type Permission = 'media' | 'geolocation' | 'notifications' | 'midiSysex' | 'pointerLock' | 'fullscreen' | 'openExternal'; + interface FromPartitionOptions { + /** + * Whether to enable cache. + */ + cache?: boolean; + } + interface ClearStorageDataOptions { /** * Should follow window.location.origin’s representation scheme://host:port. @@ -2756,21 +2944,40 @@ declare namespace Electron { quotas?: ('temporary' | 'persistent' | 'syncable')[]; } + interface ProxyConfig { + /** + * The URL associated with the PAC file. + */ + pacScript: string; + /** + * Rules indicating which proxies to use. + */ + proxyRules: string; + /** + * Rules indicating which URLs should bypass the proxy settings. + */ + proxyBypassRules: string; + } + interface NetworkEmulationOptions { /** * Whether to emulate network outage. + * Default: false. */ offline?: boolean; /** * RTT in ms. + * Default: 0, which will disable latency throttling. */ latency?: number; /** * Download rate in Bps. + * Default: 0, which will disable download throttling. */ downloadThroughput?: number; /** * Upload rate in Bps. + * Default: 0, which will disable upload throttling. */ uploadThroughput?: number; } @@ -3116,6 +3323,62 @@ declare namespace Electron { * Play the beep sound. */ beep(): void; + /** + * Creates or updates a shortcut link at shortcutPath. + * + * Note: This API is available only on Windows. + */ + writeShortcutLink(shortcutPath: string, options: ShortcutLinkOptions): boolean; + /** + * Creates or updates a shortcut link at shortcutPath. + * + * Note: This API is available only on Windows. + */ + writeShortcutLink(shortcutPath: string, operation: 'create' | 'update' | 'replace', options: ShortcutLinkOptions): boolean; + /** + * Resolves the shortcut link at shortcutPath. + * An exception will be thrown when any error happens. + * + * Note: This API is available only on Windows. + */ + readShortcutLink(shortcutPath: string): ShortcutLinkOptions; + } + + interface ShortcutLinkOptions { + /** + * The target to launch from this shortcut. + */ + target: string; + /** + * The working directory. + * Default: empty. + */ + cwd?: string; + /** + * The arguments to be applied to target when launching from this shortcut. + * Default: empty. + */ + args?: string; + /** + * The description of the shortcut. + * Default: empty. + */ + description?: string; + /** + * The path to the icon, can be a DLL or EXE. icon and iconIndex have to be set together. + * Default: empty, which uses the target's icon. + */ + icon?: string; + /** + * The resource ID of icon when icon is a DLL or EXE. + * Default: 0. + */ + iconIndex?: number; + /** + * The Application User Model ID. + * Default: empty. + */ + appUserModelId?: string; } // https://github.com/electron/electron/blob/master/docs/api/system-preferences.md @@ -3130,6 +3393,26 @@ declare namespace Electron { * Note: This is only implemented on macOS. */ isDarkMode(): boolean; + /** + * @returns If the Swipe between pages setting is on. + * + * Note: This is only implemented on macOS. + */ + isSwipeTrackingFromScrollEventsEnabled(): boolean; + /** + * Posts event as native notifications of macOS. + * The userInfo contains the user information dictionary sent along with the notification. + * + * Note: This is only implemented on macOS. + */ + postNotification(event: string, userInfo: Object): void; + /** + * Posts event as native notifications of macOS. + * The userInfo contains the user information dictionary sent along with the notification. + * + * Note: This is only implemented on macOS. + */ + postLocalNotification(event: string, userInfo: Object): void; /** * Subscribes to native notifications of macOS, callback will be called when the corresponding event happens. * The id of the subscriber is returned, which can be used to unsubscribe the event. @@ -3177,17 +3460,17 @@ declare namespace Electron { * Emitted when the tray icon is clicked. * Note: The bounds payload is only implemented on macOS and Windows. */ - on(event: 'click', listener: (modifiers: Modifiers, bounds: Bounds) => void): this; + on(event: 'click', listener: (modifiers: Modifiers, bounds: Rectangle) => void): this; /** * Emitted when the tray icon is right clicked. * Note: This is only implemented on macOS and Windows. */ - on(event: 'right-click', listener: (modifiers: Modifiers, bounds: Bounds) => void): this; + on(event: 'right-click', listener: (modifiers: Modifiers, bounds: Rectangle) => void): this; /** * Emitted when the tray icon is double clicked. * Note: This is only implemented on macOS and Windows. */ - on(event: 'double-click', listener: (modifiers: Modifiers, bounds: Bounds) => void): this; + on(event: 'double-click', listener: (modifiers: Modifiers, bounds: Rectangle) => void): this; /** * Emitted when the tray balloon shows. * Note: This is only implemented on Windows. @@ -3213,6 +3496,11 @@ declare namespace Electron { * Note: This is only implemented on macOS */ on(event: 'drop-files', listener: (event: Event, files: string[]) => void): this; + /** + * Emitted when dragged text is dropped in the tray icon. + * Note: This is only implemented on macOS + */ + on(event: 'drop-text', listener: (event: Event, text: string) => void): this; /** * Emitted when a drag operation enters the tray icon. * Note: This is only implemented on macOS @@ -3232,7 +3520,7 @@ declare namespace Electron { /** * Creates a new tray icon associated with the image. */ - new (image: NativeImage | string): Tray; + new(image: NativeImage|string): Tray; /** * Destroys the tray icon immediately. */ @@ -3240,7 +3528,7 @@ declare namespace Electron { /** * Sets the image associated with this tray icon. */ - setImage(image: NativeImage | string): void; + setImage(image: NativeImage|string): void; /** * Sets the image associated with this tray icon when pressed. */ @@ -3255,10 +3543,10 @@ declare namespace Electron { */ setTitle(title: string): void; /** - * Sets whether the tray icon is highlighted when it is clicked. + * Sets when the tray's icon background becomes highlighted. * Note: This is only implemented on macOS. */ - setHighlightMode(highlight: boolean): void; + setHighlightMode(mode: 'selection' | 'always' | 'never'): void; /** * Displays a tray balloon. * Note: This is only implemented on Windows. @@ -3282,7 +3570,7 @@ declare namespace Electron { /** * @returns The bounds of this tray icon. */ - getBounds(): Bounds; + getBounds(): Rectangle; } interface Modifiers { @@ -3292,8 +3580,31 @@ declare namespace Electron { metaKey: boolean; } + interface DragItem { + /** + * The absolute path of the file to be dragged + */ + file: string; + /** + * The image showing under the cursor when dragging. + */ + icon: NativeImage; + } + // https://github.com/electron/electron/blob/master/docs/api/web-contents.md + interface WebContentsStatic { + /** + * @returns An array of all web contents. This will contain web contents for all windows, + * webviews, opened devtools, and devtools extension background pages. + */ + getAllWebContents(): WebContents[]; + /** + * @returns The web contents that is focused in this application, otherwise returns null. + */ + getFocusedWebContents(): WebContents; + } + /** * A WebContents is responsible for rendering and controlling a web page. */ @@ -3395,7 +3706,7 @@ declare namespace Electron { * navigation outside of the page. Examples of this occurring are when anchor links * are clicked or when the DOM hashchange event is triggered. */ - on(event: 'did-navigate-in-page', listener: (event: Event, url: string) => void): this; + on(event: 'did-navigate-in-page', listener: (event: Event, url: string, isMainFrame: boolean) => void): this; /** * Emitted when the renderer process has crashed. */ @@ -3472,9 +3783,9 @@ declare namespace Electron { /** * Emitted when the cursor’s type changes. * If the type parameter is custom, the image parameter will hold the custom cursor image - * in a NativeImage, and the scale will hold scaling information for the image. + * in a NativeImage, and scale, size and hotspot will hold additional information about the custom cursor. */ - on(event: 'cursor-changed', listener: (event: Event, type: CursorType, image?: NativeImage, scale?: number) => void): this; + on(event: 'cursor-changed', listener: (event: Event, type: CursorType, image?: NativeImage, scale?: number, size?: Size, hotspot?: Point) => void): this; /** * Emitted when there is a new context menu that needs to be handled. */ @@ -3487,6 +3798,10 @@ declare namespace Electron { * passing empty string to callback will cancel the request. */ on(event: 'select-bluetooth-device', listener: (event: Event, deviceList: BluetoothDevice[], callback: (deviceId: string) => void) => void): this; + /** + * Emitted when a new frame is generated. Only the dirty area is passed in the buffer. + */ + on(event: 'paint', listener: (event: Event, dirtyRect: Rectangle, image: NativeImage) => void): this; on(event: string, listener: Function): this; /** * Loads the url in the window. @@ -3597,47 +3912,74 @@ declare namespace Electron { */ isAudioMuted(): boolean; /** - * Executes Edit -> Undo command in page. + * Changes the zoom factor to the specified factor. + * Zoom factor is zoom percent divided by 100, so 300% = 3.0. + */ + setZoomFactor(factor: number): void; + /** + * Sends a request to get current zoom factor. + */ + getZoomFactor(callback: (zoomFactor: number) => void): void; + /** + * Changes the zoom level to the specified level. + * The original size is 0 and each increment above or below represents + * zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively. + */ + setZoomLevel(level: number): void; + /** + * Sends a request to get current zoom level. + */ + getZoomLevel(callback: (zoomLevel: number) => void): void; + /** + * Sets the maximum and minimum zoom level. + */ + setZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; + /** + * Executes the editing command undo in web page. */ undo(): void; /** - * Executes Edit -> Redo command in page. + * Executes the editing command redo in web page. */ redo(): void; /** - * Executes Edit -> Cut command in page. + * Executes the editing command cut in web page. */ cut(): void; /** - * Executes Edit -> Copy command in page. + * Executes the editing command copy in web page. */ copy(): void; /** - * Executes Edit -> Paste command in page. + * Copy the image at the given position to the clipboard. + */ + copyImageAt(x: number, y: number): void; + /** + * Executes the editing command paste in web page. */ paste(): void; /** - * Executes Edit -> Paste and Match Style in page. + * Executes the editing command pasteAndMatchStyle in web page. */ pasteAndMatchStyle(): void; /** - * Executes Edit -> Delete command in page. + * Executes the editing command delete in web page. */ delete(): void; /** - * Executes Edit -> Select All command in page. + * Executes the editing command selectAll in web page. */ selectAll(): void; /** - * Executes Edit -> Unselect command in page. + * Executes the editing command unselect in web page. */ unselect(): void; /** - * Executes Edit -> Replace command in page. + * Executes the editing command replace in web page. */ replace(text: string): void; /** - * Executes Edit -> Replace Misspelling command in page. + * Executes the editing command replaceMisspelling in web page. */ replaceMisspelling(text: string): void; /** @@ -3739,16 +4081,12 @@ declare namespace Electron { * Begin subscribing for presentation events and captured frames, * The callback will be called when there is a presentation event. */ - beginFrameSubscription(callback: ( - /** - * The frameBuffer is a Buffer that contains raw pixel data. - * On most machines, the pixel data is effectively stored in 32bit BGRA format, - * but the actual representation depends on the endianness of the processor - * (most modern processors are little-endian, on machines with big-endian - * processors the data is in 32bit ARGB format). - */ - frameBuffer: Buffer - ) => void): void; + beginFrameSubscription(onlyDirty: boolean, callback: BeginFrameSubscriptionCallback): void; + /** + * Begin subscribing for presentation events and captured frames, + * The callback will be called when there is a presentation event. + */ + beginFrameSubscription(callback: BeginFrameSubscriptionCallback): void; /** * End subscribing for frame presentation events. */ @@ -3762,6 +4100,43 @@ declare namespace Electron { * Note: This API is available only on macOS. */ showDefinitionForSelection(): void; + /** + * @returns Whether offscreen rendering is enabled. + */ + isOffscreen(): boolean; + /** + * If offscreen rendering is enabled and not painting, start painting. + */ + startPainting(): void; + /** + * If offscreen rendering is enabled and painting, stop painting. + */ + stopPainting(): void; + /** + * If offscreen rendering is enabled returns whether it is currently painting. + */ + isPainting(): boolean; + /** + * If offscreen rendering is enabled sets the frame rate to the specified number. + * Only values between 1 and 60 are accepted. + */ + setFrameRate(fps: number): void; + /** + * If offscreen rendering is enabled returns the current frame rate. + */ + getFrameRate(): number; + /** + * Sets the item as dragging item for current drag-drop operation. + */ + startDrag(item: DragItem): void; + /** + * Captures a snapshot of the page within rect. + */ + capturePage(callback: (image: NativeImage) => void): void; + /** + * Captures a snapshot of the page within rect. + */ + capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; /** * @returns The unique ID of this WebContents. */ @@ -3786,6 +4161,24 @@ declare namespace Electron { debugger: Debugger; } + interface BeginFrameSubscriptionCallback { + ( + /** + * The frameBuffer is a Buffer that contains raw pixel data. + * On most machines, the pixel data is effectively stored in 32bit BGRA format, + * but the actual representation depends on the endianness of the processor + * (most modern processors are little-endian, on machines with big-endian + * processors the data is in 32bit ARGB format). + */ + frameBuffer: Buffer, + /** + * The dirtyRect is an object with x, y, width, height properties that describes which part of the page was repainted. + * If onlyDirty is set to true, frameBuffer will only contain the repainted area. onlyDirty defaults to false. + */ + dirtyRect?: Rectangle + ): void + } + interface ContextMenuParams { /** * x coordinate @@ -3825,76 +4218,76 @@ declare namespace Electron { */ mediaFlags: { /** - * Wether the media element has crashed. + * Whether the media element has crashed. */ inError: boolean; /** - * Wether the media element is paused. + * Whether the media element is paused. */ isPaused: boolean; /** - * Wether the media element is muted. + * Whether the media element is muted. */ isMuted: boolean; /** - * Wether the media element has audio. + * Whether the media element has audio. */ hasAudio: boolean; /** - * Wether the media element is looping. + * Whether the media element is looping. */ isLooping: boolean; /** - * Wether the media element's controls are visible. + * Whether the media element's controls are visible. */ isControlsVisible: boolean; /** - * Wether the media element's controls are toggleable. + * Whether the media element's controls are toggleable. */ canToggleControls: boolean; /** - * Wether the media element can be rotated. + * Whether the media element can be rotated. */ canRotate: boolean; } /** - * Wether the context menu was invoked on an image which has non-empty contents. + * Whether the context menu was invoked on an image which has non-empty contents. */ hasImageContents: boolean; /** - * Wether the context is editable. + * Whether the context is editable. */ isEditable: boolean; /** - * These flags indicate wether the renderer believes it is able to perform the corresponding action. + * These flags indicate whether the renderer believes it is able to perform the corresponding action. */ editFlags: { /** - * Wether the renderer believes it can undo. + * Whether the renderer believes it can undo. */ canUndo: boolean; /** - * Wether the renderer believes it can redo. + * Whether the renderer believes it can redo. */ canRedo: boolean; /** - * Wether the renderer believes it can cut. + * Whether the renderer believes it can cut. */ canCut: boolean; /** - * Wether the renderer believes it can copy + * Whether the renderer believes it can copy */ canCopy: boolean; /** - * Wether the renderer believes it can paste. + * Whether the renderer believes it can paste. */ canPaste: boolean; /** - * Wether the renderer believes it can delete. + * Whether the renderer believes it can delete. */ canDelete: boolean; /** - * Wether the renderer believes it can select all. + * Whether the renderer believes it can select all. */ canSelectAll: boolean; } @@ -3943,7 +4336,7 @@ declare namespace Electron { */ type StopFindInPageAtion = 'clearSelection' | 'keepSelection' | 'activateSelection'; - type CursorType = 'default' | 'crosshair' | 'pointer' | 'text' | 'wait' | 'help' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ns-resize' | 'ew-resize' | 'nesw-resize' | 'nwse-resize' | 'col-resize' | 'row-resize' | 'm-panning' | 'e-panning' | 'n-panning' | 'ne-panning' | 'nw-panning' | 's-panning' | 'se-panning' | 'sw-panning' | 'w-panning' | 'move' | 'vertical-text' | 'cell' | 'context-menu' | 'alias' | 'progress' | 'nodrop' | 'copy' | 'none' | 'not-allowed' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing' | 'custom'; + type CursorType = 'default' | 'crosshair' | 'pointer' | 'text' | 'wait' | 'help' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ns-resize' | 'ew-resize' | 'nesw-resize' | 'nwse-resize' | 'col-resize' | 'row-resize' | 'm-panning' | 'e-panning' | 'n-panning' | 'ne-panning' | 'nw-panning' | 's-panning' | 'se-panning' |'sw-panning' | 'w-panning' | 'move' | 'vertical-text' | 'cell' | 'context-menu' | 'alias' | 'progress' | 'nodrop' | 'copy' | 'none' | 'not-allowed' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing' | 'custom'; interface LoadURLOptions { /** @@ -3986,7 +4379,7 @@ declare namespace Electron { * Specify page size of the generated PDF. * Default: A4. */ - pageSize?: 'A3' | 'A4' | 'A5' | 'Legal' | 'Letter' | 'Tabloid' | Dimension; + pageSize?: 'A3' | 'A4' | 'A5' | 'Legal' | 'Letter' | 'Tabloid' | Size; /** * Whether to print CSS backgrounds. * Default: false. @@ -4006,10 +4399,33 @@ declare namespace Electron { interface Certificate { /** - * PEM encoded data + * PEM encoded data. + */ + data: string; + /** + * Issuer's Common Name. */ - data: Buffer; issuerName: string; + /** + * Subject's Common Name. + */ + subjectName: string; + /** + * Hex value represented string. + */ + serialNumber: string; + /** + * Start date of the certificate being valid in seconds. + */ + validStart: number; + /** + * End date of the certificate being valid in seconds. + */ + validExpiry: number; + /** + * Fingerprint of the certificate. + */ + fingerprint: string; } interface LoginRequest { @@ -4068,7 +4484,7 @@ declare namespace Electron { /** * Coordinates of first match region. */ - selectionArea?: Bounds; + selectionArea?: Rectangle; } interface DeviceEmulationParameters { @@ -4080,7 +4496,7 @@ declare namespace Electron { /** * Set the emulated screen size (screenPosition == mobile) */ - screenSize?: Dimension; + screenSize?: Size; /** * Position the view on the screen (screenPosition == mobile) * Default: {x: 0, y: 0} @@ -4094,7 +4510,7 @@ declare namespace Electron { /** * Set the emulated view size (empty means no override). */ - viewSize?: Dimension; + viewSize?: Size; /** * Whether emulated view should be scaled down if necessary to fit into available space * Default: false @@ -4139,7 +4555,7 @@ declare namespace Electron { wheelTicksY?: number; accelerationRatioX?: number; accelerationRatioY?: number; - hasPreciseScrollingDeltas?: number; + hasPreciseScrollingDeltas?: boolean; canScroll?: boolean; } @@ -4365,6 +4781,14 @@ declare namespace Electron { * @returns The title of guest page. */ getTitle(): string; + /** + * @returns Whether the web page is destroyed. + */ + isDestroyed(): boolean; + /** + * @returns Whether the web page is focused. + */ + isFocused(): boolean; /** * @returns Whether guest page is still loading resources. */ @@ -4416,7 +4840,7 @@ declare namespace Electron { /** * Navigates to the specified offset from the "current entry". */ - goToOffset(offset: boolean): void; + goToOffset(offset: number): void; /** * @returns Whether the renderer process has crashed. */ @@ -4556,6 +4980,14 @@ declare namespace Electron { * @returns The WebContents associated with this webview. */ getWebContents(): WebContents; + /** + * Captures a snapshot of the webview's page. Same as webContents.capturePage([rect, ]callback). + */ + capturePage(callback: (image: NativeImage) => void): void; + /** + * Captures a snapshot of the webview's page. Same as webContents.capturePage([rect, ]callback). + */ + capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; /** * Fired when a load has committed. This includes navigation within the current document * as well as subframe document-level loads, but does not include asynchronous resource loads. @@ -4634,14 +5066,14 @@ declare namespace Electron { * * Calling event.preventDefault() does NOT have any effect. */ - addEventListener(type: 'will-navigate', listener: (event: WebViewElement.NavigateEvent) => void, useCapture?: boolean): void; + addEventListener(type: 'will-navigate', listener: (event: WebViewElement.WillNavigateEvent) => void, useCapture?: boolean): void; /** * Emitted when a navigation is done. * * This event is not emitted for in-page navigations, such as clicking anchor links * or updating the window.location.hash. Use did-navigate-in-page event for this purpose. */ - addEventListener(type: 'did-navigate', listener: (event: WebViewElement.NavigateEvent) => void, useCapture?: boolean): void; + addEventListener(type: 'did-navigate', listener: (event: WebViewElement.DidNavigateEvent) => void, useCapture?: boolean): void; /** * Emitted when an in-page navigation happened. * @@ -4649,7 +5081,7 @@ declare namespace Electron { * navigation outside of the page. Examples of this occurring are when anchor links * are clicked or when the DOM hashchange event is triggered. */ - addEventListener(type: 'did-navigate-in-page', listener: (event: WebViewElement.NavigateEvent) => void, useCapture?: boolean): void; + addEventListener(type: 'did-navigate-in-page', listener: (event: WebViewElement.DidNavigateInPageEvent) => void, useCapture?: boolean): void; /** * Fired when the guest page attempts to close itself. */ @@ -4709,23 +5141,23 @@ declare namespace Electron { namespace WebViewElement { type Event = ElectronPrivate.GlobalEvent; - interface LoadCommitEvent extends Event { + interface LoadCommitEvent extends Event { url: string; isMainFrame: boolean; } - interface DidFailLoadEvent extends Event { + interface DidFailLoadEvent extends Event { errorCode: number; errorDescription: string; validatedURL: string; isMainFrame: boolean; } - interface DidFrameFinishLoadEvent extends Event { + interface DidFrameFinishLoadEvent extends Event { isMainFrame: boolean; } - interface DidGetResponseDetails extends Event { + interface DidGetResponseDetails extends Event { status: boolean; newURL: string; originalURL: string; @@ -4773,10 +5205,19 @@ declare namespace Electron { options: BrowserWindowOptions; } - interface NavigateEvent extends Event { + interface WillNavigateEvent extends Event { url: string; } + interface DidNavigateEvent extends Event { + url: string; + } + + interface DidNavigateInPageEvent extends Event { + url: string; + isMainFrame: boolean; + } + interface IpcMessageEvent extends Event { channel: string; args: any[]; @@ -4856,7 +5297,7 @@ declare namespace Electron { session: typeof Electron.Session; systemPreferences: Electron.SystemPreferences; Tray: Electron.Tray; - hideInternalModules(): void; + webContents: Electron.WebContentsStatic; } interface ElectronMainAndRenderer extends CommonElectron { @@ -4896,6 +5337,18 @@ interface File { // https://github.com/electron/electron/blob/master/docs/api/process.md declare namespace NodeJS { + + interface ProcessVersions { + /** + * Electron's version string. + */ + electron: string; + /** + * Chrome's version string. + */ + chrome: string; + } + interface Process { /** * Setting this to true can disable the support for asar archives in Node's built-in modules. diff --git a/src/vs/base/node/stdFork.ts b/src/vs/base/node/stdFork.ts index 3f5a4a3f7f3..4e20df2187e 100644 --- a/src/vs/base/node/stdFork.ts +++ b/src/vs/base/node/stdFork.ts @@ -49,7 +49,7 @@ function generatePatchedEnv(env:any, stdInPipeName:string, stdOutPipeName:string newEnv['STDIN_PIPE_NAME'] = stdInPipeName; newEnv['STDOUT_PIPE_NAME'] = stdOutPipeName; newEnv['STDERR_PIPE_NAME'] = stdErrPipeName; - newEnv['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = '1'; + newEnv['ELECTRON_RUN_AS_NODE'] = '1'; return newEnv; } diff --git a/src/vs/base/node/stdForkStart.js b/src/vs/base/node/stdForkStart.js index 0b1e7382fe5..92024acf6b8 100644 --- a/src/vs/base/node/stdForkStart.js +++ b/src/vs/base/node/stdForkStart.js @@ -33,7 +33,7 @@ var stdErrPipeName = process.env['STDERR_PIPE_NAME']; log('STDIN_PIPE_NAME: ' + stdInPipeName); log('STDOUT_PIPE_NAME: ' + stdOutPipeName); log('STDERR_PIPE_NAME: ' + stdErrPipeName); -log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']); +log('ELECTRON_RUN_AS_NODE: ' + process.env['ELECTRON_RUN_AS_NODE']); // stdout redirection to named pipe (function() { @@ -149,7 +149,7 @@ log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_A delete process.env['STDIN_PIPE_NAME']; delete process.env['STDOUT_PIPE_NAME']; delete process.env['STDERR_PIPE_NAME']; - delete process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete process.env['ELECTRON_RUN_AS_NODE']; require(program); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 0d0b3e365f0..e75241ab340 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -273,13 +273,13 @@ interface IEnv { function getUnixShellEnvironment(): TPromise { const promise = new TPromise((c, e) => { - const runAsNode = process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + const runAsNode = process.env['ELECTRON_RUN_AS_NODE']; const noAttach = process.env['ELECTRON_NO_ATTACH_CONSOLE']; const mark = generateUuid().replace(/-/g, '').substr(0, 12); const regex = new RegExp(mark + '(.*)' + mark); const env = assign({}, process.env, { - ATOM_SHELL_INTERNAL_RUN_AS_NODE: '1', + ELECTRON_RUN_AS_NODE: '1', ELECTRON_NO_ATTACH_CONSOLE: '1' }); @@ -307,9 +307,9 @@ function getUnixShellEnvironment(): TPromise { const env = JSON.parse(rawStripped); if (runAsNode) { - env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = runAsNode; + env['ELECTRON_RUN_AS_NODE'] = runAsNode; } else { - delete env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete env['ELECTRON_RUN_AS_NODE']; } if (noAttach) { diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index b8bbfc60312..800d5554362 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -568,7 +568,7 @@ export class VSCodeWindow { return null; } - public getBounds(): Electron.Bounds { + public getBounds(): Electron.Rectangle { const pos = this.win.getPosition(); const dimension = this.win.getSize(); diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 3a506b9d96a..946a0cc568c 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -41,7 +41,7 @@ export function main(argv: string[]): TPromise { 'VSCODE_CLI': '1', 'ELECTRON_NO_ATTACH_CONSOLE': '1' }); - delete env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete env['ELECTRON_RUN_AS_NODE']; let options = { detached: true, diff --git a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css index 272e8c6fd1f..8bf1d15303d 100644 --- a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css +++ b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css @@ -12,7 +12,8 @@ cursor: default; } -.monaco-workbench .monaco-editor .margin-view-overlays .line-numbers { +/* disable until https://github.com/Microsoft/vscode/issues/8708 is fixed */ +/*.monaco-workbench .monaco-editor .margin-view-overlays .line-numbers { cursor: -webkit-image-set( url('flipped-cursor.svg') 1x, url('flipped-cursor-2x.svg') 2x @@ -24,7 +25,7 @@ url('flipped-cursor-mac.svg') 1x, url('flipped-cursor-mac-2x.svg') 2x ) 24 3, default; -} +}*/ .monaco-editor .margin-view-overlays .line-numbers.lh-odd { margin-top: 1px; diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index d7f264091d7..2fc38e6fa79 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -607,7 +607,7 @@ export class DebugService implements debug.IDebugService { timeout: 1000 * 60 * 5, args: [`${ publisher }.${ type }`, JSON.stringify(data), aiKey], env: { - ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1, + ELECTRON_RUN_AS_NODE: 1, PIPE_LOGGING: 'true', AMD_ENTRYPOINT: 'vs/workbench/parts/debug/node/telemetryApp' } diff --git a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts index 59e84d0d967..fa51cb29a32 100644 --- a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts +++ b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts @@ -158,7 +158,7 @@ function createRemoteRawGitService(gitPath: string, execPath: string, workspaceR timeout: 1000 * 60, args: [path, workspaceRoot, encoding, execPath, version], env: { - ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1, + ELECTRON_RUN_AS_NODE: 1, PIPE_LOGGING: 'true', AMD_ENTRYPOINT: 'vs/workbench/parts/git/node/gitApp', VERBOSE_LOGGING: String(verbose) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js b/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js index 5b383f8f17b..9b38c52dd7f 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js @@ -65,7 +65,7 @@ function getArgs() { function cleanEnv() { var keys = [ - 'ATOM_SHELL_INTERNAL_RUN_AS_NODE', + 'ELECTRON_RUN_AS_NODE', 'PTYCWD', 'PTYPID', 'PTYSHELL' diff --git a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts index a5956e04643..d6a9ab0da6c 100644 --- a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts +++ b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts @@ -54,7 +54,7 @@ export class ContextMenuService implements IContextMenuService { x *= zoom; y *= zoom; - menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y), -1 /* no item selected by default */); + menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y)); if (delegate.onHide) { delegate.onHide(undefined); } From f26cf83dd8313a6f9afc188433e52ebf6d84ac10 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 13 Sep 2016 17:26:10 +0200 Subject: [PATCH 12/23] print commit in new line --- src/vs/code/node/cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 946a0cc568c..18e6d60018c 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -31,7 +31,7 @@ export function main(argv: string[]): TPromise { if (args.help) { console.log(buildHelpMessage(product.nameLong, product.applicationName, pkg.version)); } else if (args.version) { - console.log(`${ pkg.version } (${ product.commit })`); + console.log(`${ pkg.version }\n${ product.commit }`); } else if (shouldSpawnCliProcess(args)) { const mainCli = new TPromise(c => require(['vs/code/node/cliProcessMain'], c)); return mainCli.then(cli => cli.main(args)); From b17fe30fb657e3ae9465b8ea00123ce0e029bc82 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 14 Sep 2016 10:22:37 +0200 Subject: [PATCH 13/23] fix #11967 --- src/vs/editor/contrib/find/browser/find.ts | 2 +- .../editor/contrib/find/browser/findWidget.ts | 11 +++- .../contrib/find/common/findController.ts | 17 +++++-- .../editor/contrib/find/common/findModel.ts | 50 +++++++++++-------- .../search/browser/search.contribution.ts | 10 ++-- 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/vs/editor/contrib/find/browser/find.ts b/src/vs/editor/contrib/find/browser/find.ts index 6924b1dc3cf..06ddc371a85 100644 --- a/src/vs/editor/contrib/find/browser/find.ts +++ b/src/vs/editor/contrib/find/browser/find.ts @@ -25,7 +25,7 @@ class FindController extends CommonFindController implements IFindController { ) { super(editor, contextKeyService); - this._widget = this._register(new FindWidget(editor, this, this._state, contextViewService, keybindingService)); + this._widget = this._register(new FindWidget(editor, this, this._state, contextViewService, keybindingService, contextKeyService)); } protected _start(opts:IFindStartOptions): void { diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index ed0825ff8d9..bd692ce101e 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -22,6 +22,8 @@ import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositi import {FIND_IDS, MATCHES_LIMIT} from 'vs/editor/contrib/find/common/findModel'; import {FindReplaceState, FindReplaceStateChangedEvent} from 'vs/editor/contrib/find/common/findState'; import {Range} from 'vs/editor/common/core/range'; +import {IContextKeyService, IContextKey} from 'vs/platform/contextkey/common/contextkey'; +import {CONTEXT_FIND_INPUT_FOCUSSED} from 'vs/editor/contrib/find/common/findController'; export interface IFindController { replace(): void; @@ -75,13 +77,15 @@ export class FindWidget extends Widget implements IOverlayWidget { private _isReplaceVisible: boolean; private _focusTracker: dom.IFocusTracker; + private _findInputFocussed: IContextKey; constructor( codeEditor: ICodeEditor, controller: IFindController, state: FindReplaceState, contextViewProvider: IContextViewProvider, - keybindingService: IKeybindingService + keybindingService: IKeybindingService, + contextKeyService: IContextKeyService ) { super(); this._codeEditor = codeEditor; @@ -112,8 +116,10 @@ export class FindWidget extends Widget implements IOverlayWidget { this._updateToggleSelectionFindButton(); } })); + this._findInputFocussed = CONTEXT_FIND_INPUT_FOCUSSED.bindTo(contextKeyService); this._focusTracker = this._register(dom.trackFocus(this._findInput.inputBox.inputElement)); this._focusTracker.addFocusListener(() => { + this._findInputFocussed.set(true); let selection = this._codeEditor.getSelection(); let currentMatch = this._state.currentMatch; if (selection.startLineNumber !== selection.endLineNumber) { @@ -123,6 +129,9 @@ export class FindWidget extends Widget implements IOverlayWidget { } } }); + this._focusTracker.addBlurListener(() => { + this._findInputFocussed.set(false); + }); this._codeEditor.addOverlayWidget(this); } diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index be75e59688a..4f3319fc4f3 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -14,7 +14,7 @@ import {Selection} from 'vs/editor/common/core/selection'; import * as strings from 'vs/base/common/strings'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {editorAction, commonEditorContribution, ServicesAccessor, EditorAction, EditorCommand, CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding} from 'vs/editor/contrib/find/common/findModel'; +import {FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ShowPreviousFindTermKeybinding, ShowNextFindTermKeybinding} from 'vs/editor/contrib/find/common/findModel'; import {FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState} from 'vs/editor/contrib/find/common/findState'; import {DocumentHighlightProviderRegistry} from 'vs/editor/common/modes'; import {RunOnceScheduler, Delayer} from 'vs/base/common/async'; @@ -36,6 +36,7 @@ export interface IFindStartOptions { export const CONTEXT_FIND_WIDGET_VISIBLE = new RawContextKey('findWidgetVisible', false); export const CONTEXT_FIND_WIDGET_NOT_VISIBLE: ContextKeyExpr = CONTEXT_FIND_WIDGET_VISIBLE.toNegated(); +export const CONTEXT_FIND_INPUT_FOCUSSED = new RawContextKey('findInputFocussed', false); export class CommonFindController extends Disposable implements editorCommon.IEditorContribution { @@ -994,8 +995,11 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ handler: x => x.showPreviousFindTerm(), kbOpts: { weight: CommonEditorRegistry.commandWeight(5), - kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.UpArrow + kbExpr: ContextKeyExpr.and(CONTEXT_FIND_INPUT_FOCUSSED, EditorContextKeys.Focus), + primary: ShowPreviousFindTermKeybinding.primary, + mac: ShowPreviousFindTermKeybinding.mac, + win: ShowPreviousFindTermKeybinding.win, + linux: ShowPreviousFindTermKeybinding.linux } })); @@ -1005,7 +1009,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ handler: x => x.showNextFindTerm(), kbOpts: { weight: CommonEditorRegistry.commandWeight(5), - kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.DownArrow + kbExpr: ContextKeyExpr.and(CONTEXT_FIND_INPUT_FOCUSSED, EditorContextKeys.Focus), + primary: ShowNextFindTermKeybinding.primary, + mac: ShowNextFindTermKeybinding.mac, + win: ShowNextFindTermKeybinding.win, + linux: ShowNextFindTermKeybinding.linux } })); diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index bb0796feda1..2a1e47da5ea 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -31,6 +31,12 @@ export const ToggleRegexKeybinding: IKeybindings = { primary: KeyMod.Alt | KeyCode.KEY_R, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } }; +export const ShowPreviousFindTermKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.UpArrow +}; +export const ShowNextFindTermKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.DownArrow +}; export const FIND_IDS = { StartFindAction: 'actions.find', @@ -58,16 +64,16 @@ export const MATCHES_LIMIT = 999; export class FindModelBoundToEditorModel { - private _editor:editorCommon.ICommonCodeEditor; - private _state:FindReplaceState; - private _toDispose:IDisposable[]; + private _editor: editorCommon.ICommonCodeEditor; + private _state: FindReplaceState; + private _toDispose: IDisposable[]; private _decorations: FindDecorations; - private _ignoreModelContentChanged:boolean; + private _ignoreModelContentChanged: boolean; - private _updateDecorationsScheduler:RunOnceScheduler; + private _updateDecorationsScheduler: RunOnceScheduler; private _isDisposed: boolean; - constructor(editor:editorCommon.ICommonCodeEditor, state:FindReplaceState) { + constructor(editor: editorCommon.ICommonCodeEditor, state: FindReplaceState) { this._editor = editor; this._state = state; this._toDispose = []; @@ -79,7 +85,7 @@ export class FindModelBoundToEditorModel { this._updateDecorationsScheduler = new RunOnceScheduler(() => this.research(false), 100); this._toDispose.push(this._updateDecorationsScheduler); - this._toDispose.push(this._editor.onDidChangeCursorPosition((e:editorCommon.ICursorPositionChangedEvent) => { + this._toDispose.push(this._editor.onDidChangeCursorPosition((e: editorCommon.ICursorPositionChangedEvent) => { if ( e.reason === editorCommon.CursorChangeReason.Explicit || e.reason === editorCommon.CursorChangeReason.Undo @@ -90,7 +96,7 @@ export class FindModelBoundToEditorModel { })); this._ignoreModelContentChanged = false; - this._toDispose.push(this._editor.onDidChangeModelRawContent((e:editorCommon.IModelContentChangedEvent) => { + this._toDispose.push(this._editor.onDidChangeModelRawContent((e: editorCommon.IModelContentChangedEvent) => { if (this._ignoreModelContentChanged) { return; } @@ -112,7 +118,7 @@ export class FindModelBoundToEditorModel { this._toDispose = dispose(this._toDispose); } - private _onStateChanged(e:FindReplaceStateChangedEvent): void { + private _onStateChanged(e: FindReplaceStateChangedEvent): void { if (this._isDisposed) { // The find model is disposed during a find state changed event return; @@ -126,8 +132,8 @@ export class FindModelBoundToEditorModel { } } - private static _getSearchRange(model:editorCommon.IModel, searchOnlyEditableRange:boolean, findScope:Range): Range { - let searchRange:Range; + private static _getSearchRange(model: editorCommon.IModel, searchOnlyEditableRange: boolean, findScope: Range): Range { + let searchRange: Range; if (searchOnlyEditableRange) { searchRange = model.getEditableRange(); @@ -143,7 +149,7 @@ export class FindModelBoundToEditorModel { return searchRange; } - private research(moveCursor:boolean, newFindScope?:Range): void { + private research(moveCursor: boolean, newFindScope?: Range): void { let findScope: Range = null; if (typeof newFindScope !== 'undefined') { findScope = newFindScope; @@ -184,7 +190,7 @@ export class FindModelBoundToEditorModel { return false; } - private _setCurrentFindMatch(match:Range): void { + private _setCurrentFindMatch(match: Range): void { let matchesPosition = this._decorations.setCurrentFindMatch(match); this._state.changeMatchInfo( matchesPosition, @@ -196,7 +202,7 @@ export class FindModelBoundToEditorModel { this._editor.revealRangeInCenterIfOutsideViewport(match); } - private _moveToPrevMatch(before:Position, isRecursed:boolean = false): void { + private _moveToPrevMatch(before: Position, isRecursed: boolean = false): void { if (this._cannotFind()) { return; } @@ -214,7 +220,7 @@ export class FindModelBoundToEditorModel { before = searchRange.getEndPosition(); } - let {lineNumber,column} = before; + let {lineNumber, column} = before; let model = this._editor.getModel(); let position = new Position(lineNumber, column); @@ -260,8 +266,8 @@ export class FindModelBoundToEditorModel { this._moveToPrevMatch(this._editor.getSelection().getStartPosition()); } - private _moveToNextMatch(nextMatch:Range): void - private _moveToNextMatch(after:Position): void + private _moveToNextMatch(nextMatch: Range): void + private _moveToNextMatch(after: Position): void private _moveToNextMatch(arg: any): void { let nextMatch = Range.isIRange(arg) ? arg : Position.isIPosition(arg) ? this._getNextMatch(arg) : null; if (nextMatch) { @@ -269,7 +275,7 @@ export class FindModelBoundToEditorModel { } } - private _getNextMatch(after:Position, isRecursed:boolean = false): Range { + private _getNextMatch(after: Position, isRecursed: boolean = false): Range { if (this._cannotFind()) { return null; } @@ -287,7 +293,7 @@ export class FindModelBoundToEditorModel { after = searchRange.getStartPosition(); } - let {lineNumber,column} = after; + let {lineNumber, column} = after; let model = this._editor.getModel(); let position = new Position(lineNumber, column); @@ -385,7 +391,7 @@ export class FindModelBoundToEditorModel { } } - private _findMatches(findScope: Range, limitResultCount:number): Range[] { + private _findMatches(findScope: Range, limitResultCount: number): Range[] { let searchRange = FindModelBoundToEditorModel._getSearchRange(this._editor.getModel(), this._state.isReplaceRevealed, findScope); return this._editor.getModel().findMatches(this._state.searchString, searchRange, this._state.isRegex, this._state.matchCase, this._state.wholeWord, limitResultCount); } @@ -400,7 +406,7 @@ export class FindModelBoundToEditorModel { // Get all the ranges (even more than the highlighted ones) let ranges = this._findMatches(findScope, Number.MAX_VALUE); - let replaceStrings:string[] = []; + let replaceStrings: string[] = []; for (let i = 0, len = ranges.length; i < len; i++) { replaceStrings.push(this.getReplaceString(ranges[i])); } @@ -424,7 +430,7 @@ export class FindModelBoundToEditorModel { this._editor.setSelections(ranges.map(r => new Selection(r.startLineNumber, r.startColumn, r.endLineNumber, r.endColumn))); } - private _executeEditorCommand(source:string, command:editorCommon.ICommand): void { + private _executeEditorCommand(source: string, command: editorCommon.ICommand): void { try { this._ignoreModelContentChanged = true; this._editor.executeCommand(source, command); diff --git a/src/vs/workbench/parts/search/browser/search.contribution.ts b/src/vs/workbench/parts/search/browser/search.contribution.ts index 782ac6ec7b5..9819545ae25 100644 --- a/src/vs/workbench/parts/search/browser/search.contribution.ts +++ b/src/vs/workbench/parts/search/browser/search.contribution.ts @@ -30,7 +30,7 @@ import * as Constants from 'vs/workbench/parts/search/common/constants'; import { registerContributions as replaceContributions } from 'vs/workbench/parts/search/browser/replaceContributions'; import { registerContributions as searchWidgetContributions } from 'vs/workbench/parts/search/browser/searchWidget'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding } from 'vs/editor/contrib/find/common/findModel'; +import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ShowPreviousFindTermKeybinding, ShowNextFindTermKeybinding } from 'vs/editor/contrib/find/common/findModel'; replaceContributions(); searchWidgetContributions(); @@ -166,13 +166,9 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ShowAllSymbolsAction, primary: KeyMod.CtrlCmd | KeyCode.KEY_T }), 'Show All Symbols'); -registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowNextSearchTermAction, searchActions.ShowNextSearchTermAction.ID, searchActions.ShowNextSearchTermAction.LABEL, { - primary: KeyMod.Alt | KeyCode.DownArrow -}, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowNextSearchTermAction, searchActions.ShowNextSearchTermAction.ID, searchActions.ShowNextSearchTermAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); -registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowPreviousSearchTermAction, searchActions.ShowPreviousSearchTermAction.ID, searchActions.ShowPreviousSearchTermAction.LABEL, { - primary: KeyMod.Alt | KeyCode.UpArrow -}, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowPreviousSearchTermAction, searchActions.ShowPreviousSearchTermAction.ID, searchActions.ShowPreviousSearchTermAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FocusNextInputAction, searchActions.FocusNextInputAction.ID, searchActions.FocusNextInputAction.LABEL, { primary: KeyCode.DownArrow From 4e59a0c754382fb58ccb485c4bdf8e6bfcaafddf Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Sep 2016 10:56:38 +0200 Subject: [PATCH 14/23] getPathLabel(): Cannot read property '1' of null (fixes #11962) --- src/vs/base/common/labels.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 96a51f345b1..3c37260ff8e 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -36,9 +36,13 @@ export class PathLabelProvider implements ILabelProvider { } } -export function getPathLabel(arg1: URI | string, arg2?: URI | string | IWorkspaceProvider): string { - let basepath = arg2 && getPath(arg2); - let absolutePath = getPath(arg1); +export function getPathLabel(resource: URI | string, basePathProvider?: URI | string | IWorkspaceProvider): string { + const absolutePath = getPath(resource); + if (!absolutePath) { + return null; + } + + const basepath = basePathProvider && getPath(basePathProvider); if (basepath && paths.isEqualOrParent(absolutePath, basepath)) { if (basepath === absolutePath) { @@ -48,7 +52,7 @@ export function getPathLabel(arg1: URI | string, arg2?: URI | string | IWorkspac return paths.normalize(strings.ltrim(absolutePath.substr(basepath.length), paths.nativeSep), true); } - if (platform.isWindows && absolutePath[1] === ':') { + if (platform.isWindows && absolutePath && absolutePath[1] === ':') { return paths.normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), true); } @@ -65,7 +69,7 @@ function getPath(arg1: URI | string | IWorkspaceProvider): string { } if (types.isFunction((arg1).getWorkspace)) { - let ws = (arg1).getWorkspace(); + const ws = (arg1).getWorkspace(); return ws ? ws.resource.fsPath : void 0; } From 5cc7faabc2048c306d90a74f0b5580467b7f4b0c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Sep 2016 11:33:10 +0200 Subject: [PATCH 15/23] add icon to cat.exe --- resources/win32/bin/cat.exe | Bin 10240 -> 40448 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/win32/bin/cat.exe b/resources/win32/bin/cat.exe index 5fcc054e438938165161ede4e41d89202c797df0..f564baa192a0c7af76e09d32f1c2b1164bdee9a3 100644 GIT binary patch literal 40448 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 z zh<^d^8;U+IOXRwd&%^re!T*|eivhJsY%_Sy7q8P1v!AxMi)kgDBjk_iFHiolYyXqf z*8e=~uKy8~cZ-3*k7$J3Dse44+(^EUTeQ>b=D0@;B79Trn4pj3i~YZ7wP?-} z$6vEVf9uV$tQfkZ-y2%pT_Xzyg1)Cp7yi4eySKmhjDd`AaQw~r^($zuujsX&-vxuj z@kh~%BQ@~%jDsjS;PDrZXQ}a5X_8L>9)I~h>DzISB-u1n6_|2vn+S7)oL<%BKX=co zdVk|j3J)58Yd?GmW2p0g_gy7`^CU{>!$6yyy#CD7tvv#N#s> zL_Cex+2J~f@_`4;bMCns#yJnca~vo}`5YpxX^{9mD?j$==(m-RMOgSbu~1v`k{GKH;~0$9ra!z6^+3yFn~B(|@X6KoxB-{X>Qug_I9;rK znAGxvASdX6DTO~b;ta$dozjj!=IG?QF8GsfiqIc~CDiT?3hst!u`r2Z5M{gbvL?Hk#z2#$99b;tJWX(+8^$A72}WXHJuBpjbsC0qNU zY5{s_THxHbYrj+-lJ<1sEuf^A!EeGvZ-+%U0%Me3~emgmd3U-4K2-e zce2fA*{dlt&}-#QjE&f~n?$Lhsu+wpwl;Qb+vOI8!0nX+UuF4(mjtiNEiJA2TC232w2o?dX?bhKYCYAe z(h_RXW~UMUV2x+ZU}>}Fu@on^J zmKV#Lb&ciA@@ECJLRnF)1lDs_DhmfoI4K*WnyC6xH5)?(CWESMa{XvK7aWul@mW5VQB zjQ_YUumB|kfS7IaCMIRh1R#qEh}AaVV>08jh8YJEN(SO5ia;y~WB>t74rICr5PK*A zu@FcGEH~L-P?8y_W^%S*uR0r0%-Jd?v^ce>I3}qe5lH99xa237=BDPA6vu>R7MCXG zCRhOV Date: Wed, 14 Sep 2016 12:48:37 +0200 Subject: [PATCH 16/23] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 5aebf4f06cc..2a2679bd2eb 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "85ec7d8/node-debug.zip", + "zip": "9263600/node-debug.zip", "output": "" } From 368be109ba38938e89551ac15a58ccfd31a460e8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Sep 2016 16:07:06 +0200 Subject: [PATCH 17/23] Explorer no longer shows "..." for cropped file labels (fixes #12022) --- .../workbench/parts/files/browser/media/explorerviewlet.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/parts/files/browser/media/explorerviewlet.css b/src/vs/workbench/parts/files/browser/media/explorerviewlet.css index 5dbaac7ee5e..e0f99c3f6cd 100644 --- a/src/vs/workbench/parts/files/browser/media/explorerviewlet.css +++ b/src/vs/workbench/parts/files/browser/media/explorerviewlet.css @@ -15,6 +15,11 @@ line-height: 22px; } +.explorer-viewlet .explorer-item { + display: flex; /* this helps showing the overflow ellipsis (...) even though we use display:inline-block for the labels */ + flex-wrap: nowrap; +} + .explorer-viewlet .explorer-item-label, .explorer-viewlet .open-editor, .explorer-viewlet .editor-group { @@ -25,6 +30,7 @@ .explorer-viewlet .explorer-item-label, .explorer-viewlet .explorer-item .monaco-inputbox { display: inline-block; /* required for icons support :before rule */ + flex: 1; } .explorer-viewlet .explorer-open-editors .monaco-tree .monaco-tree-row > .content { From 5f29eb75239761f1dda03bb6e04832aec3c67527 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Sep 2016 16:16:06 +0200 Subject: [PATCH 18/23] Explorer: files with spaces produces bad CSS classes (fixes #12024) --- .../parts/files/browser/views/explorerViewer.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 70e41699ed8..24758a21ce8 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -398,19 +398,19 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { const name = dotSegments[0]; // file.txt => "file", .dockerfile => "", file.some.txt => "file" if (name) { - classes.push(`${name.toLowerCase()}-name-file-icon`); + classes.push(`${this.cssEscape(name.toLowerCase())}-name-file-icon`); } const extensions = dotSegments.splice(1); if (extensions.length > 0) { for (let i = 0; i < extensions.length; i++) { - classes.push(`${extensions.slice(i).join('.').toLowerCase()}-ext-file-icon`); // add each combination of all found extensions if more than one + classes.push(`${this.cssEscape(extensions.slice(i).join('.').toLowerCase())}-ext-file-icon`); // add each combination of all found extensions if more than one } } const langId = this.modeService.getModeIdByFilenameOrFirstLine(fsPath); if (langId) { - classes.push(`${langId}-lang-file-icon`); + classes.push(`${this.cssEscape(langId)}-lang-file-icon`); } return classes; @@ -422,11 +422,15 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { const classes = ['folder-icon']; if (basename) { - classes.push(`${basename.toLowerCase()}-name-folder-icon`); + classes.push(`${this.cssEscape(basename.toLowerCase())}-name-folder-icon`); } return classes; } + + private cssEscape(val: string): string { + return val.replace(/ /g, '\\ '); // make sure to not introduce CSS classes from files that contain whitespace + } } // Explorer Accessibility Provider From cd1318c7b83a61b00cf061e7db07f849279baafa Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Sep 2016 16:19:55 +0200 Subject: [PATCH 19/23] better fix for css escaping in explorer --- src/vs/workbench/parts/files/browser/views/explorerViewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 24758a21ce8..e80253e0029 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -429,7 +429,7 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { } private cssEscape(val: string): string { - return val.replace(/ /g, '\\ '); // make sure to not introduce CSS classes from files that contain whitespace + return val.replace(/\s/g, '\\$&'); // make sure to not introduce CSS classes from files that contain whitespace } } From 94eb60a29272ba41273c76c821cc8900f028dc67 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 14 Sep 2016 17:00:08 +0200 Subject: [PATCH 20/23] fix fsevents compatibility for build tools --- build/lib/watch/index.js | 10 ++++++---- build/lib/watch/package.json | 16 ++++++++-------- build/npm/preinstall.js | 27 ++++++++++++++++++++++++--- package.json | 1 - 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/build/lib/watch/index.js b/build/lib/watch/index.js index 6c141221047..6f71cb36761 100644 --- a/build/lib/watch/index.js +++ b/build/lib/watch/index.js @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -var es = require('event-stream'); +const es = require('event-stream'); /** Ugly hack for gulp-tsb */ function handleDeletions() { - return es.mapSync(function (f) { + return es.mapSync(f => { if (/\.ts$/.test(f.relative) && !f.contents) { f.contents = new Buffer(''); f.stat = { mtime: new Date() }; @@ -17,9 +17,11 @@ function handleDeletions() { }); } -var watch = process.platform === 'win32' ? require('./watch-win32') : require('gulp-watch'); +const watch = process.platform === 'win32' + ? require('./watch-win32') + : require('gulp-watch'); -module.exports = function () { +module.exports = () => { return watch.apply(null, arguments) .pipe(handleDeletions()); }; diff --git a/build/lib/watch/package.json b/build/lib/watch/package.json index 47bf00b77f1..0d031340153 100644 --- a/build/lib/watch/package.json +++ b/build/lib/watch/package.json @@ -1,10 +1,10 @@ { - "name": "watch", - "version": "1.0.0", - "description": "", - "author": "Microsoft ", - "private": true, - "devDependencies": { - "gulp-watch": "^4.3.5" - } + "name": "watch", + "version": "1.0.0", + "description": "", + "author": "Microsoft ", + "private": true, + "devDependencies": { + "gulp-watch": "^4.3.9" + } } diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index 124013231d7..6a65998d3f6 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -3,11 +3,32 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -var win = "Please run '.\\scripts\\npm.bat install' instead."; -var nix = "Please run './scripts/npm.sh install' instead."; +const path = require('path'); +const cp = require('child_process'); if (process.env['npm_config_disturl'] !== 'https://atom.io/download/atom-shell') { console.error("You can't use plain npm to install Code's dependencies."); - console.error(/^win/.test(process.platform) ? win : nix); + console.error( + /^win/.test(process.platform) + ? "Please run '.\\scripts\\npm.bat install' instead." + : "Please run './scripts/npm.sh install' instead." + ); + process.exit(1); } + +// make sure we install gulp watch for the system installed +// node, since that is the driver of gulp +if (process.platform !== 'win32') { + const env = Object.assign({}, process.env); + + delete env['npm_config_disturl']; + delete env['npm_config_target']; + delete env['npm_config_runtime']; + + cp.spawnSync('npm', ['install'], { + cwd: path.join(path.dirname(__dirname), 'lib', 'watch'), + stdio: 'inherit', + env + }); +} \ No newline at end of file diff --git a/package.json b/package.json index 75cfedab218..ea947787c97 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,6 @@ "gulp-uglify": "^1.4.1", "gulp-util": "^3.0.6", "gulp-vinyl-zip": "^1.2.2", - "gulp-watch": "4.3.6", "innosetup-compiler": "^5.5.60", "is": "^3.1.0", "istanbul": "^0.3.17", From bf65a1907d0656e200cf15ae92ad0d3d1b7b3aaf Mon Sep 17 00:00:00 2001 From: Denis Malinochkin Date: Wed, 14 Sep 2016 18:23:30 +0300 Subject: [PATCH 21/23] Display language identifier in Language Mode drop down --- src/vs/workbench/browser/parts/editor/editorStatus.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 0324fd61340..a61faa1779b 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -662,9 +662,12 @@ export class ChangeModeAction extends Action { // All languages are valid picks const picks: IPickOpenEntry[] = languages.sort().map((lang, index) => { - return { + const languageModeId = this.modeService.getModeIdForLanguageName(lang.toLowerCase()); + const configureLabel = nls.localize('configuredLanguage', "Configured Language"); + + return { label: lang, - description: currentModeId === lang ? nls.localize('configuredLanguage', "Configured Language") : void 0 + description: currentModeId === lang ? `${languageModeId} (${configureLabel})` : languageModeId }; }); picks[0].separator = { border: true, label: nls.localize('languagesPicks', "languages") }; From af877ffb5325d024d333ae720bc30bcab63a0359 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Sep 2016 17:44:06 +0200 Subject: [PATCH 22/23] fix gulp watch --- build/lib/watch/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/lib/watch/index.js b/build/lib/watch/index.js index 6f71cb36761..17cd6ab6646 100644 --- a/build/lib/watch/index.js +++ b/build/lib/watch/index.js @@ -21,7 +21,7 @@ const watch = process.platform === 'win32' ? require('./watch-win32') : require('gulp-watch'); -module.exports = () => { +module.exports = function () { return watch.apply(null, arguments) .pipe(handleDeletions()); }; From fc54f4b15d752c18311255c12ab186361406afb7 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 14 Sep 2016 17:54:39 +0200 Subject: [PATCH 23/23] use opener service in extension editor fixes #11309 --- .../extensions/electron-browser/extensionEditor.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts index 195c970b017..ab5fab917dd 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts @@ -42,6 +42,7 @@ import { Keybinding } from 'vs/base/common/keyCodes'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { IMessageService } from 'vs/platform/message/common/message'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; function renderBody(body: string): string { return ` @@ -140,7 +141,8 @@ export class ExtensionEditor extends BaseEditor { @IThemeService private themeService: IThemeService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IKeybindingService private keybindingService: IKeybindingService, - @IMessageService private messageService: IMessageService + @IMessageService private messageService: IMessageService, + @IOpenerService private openerService: IOpenerService ) { super(ExtensionEditor.ID, telemetryService); this._highlight = null; @@ -276,9 +278,9 @@ export class ExtensionEditor extends BaseEditor { webview.style(this.themeService.getColorTheme()); webview.contents = [body]; - const linkListener = webview.onDidClickLink(link => shell.openExternal(link.toString(true))); - const themeListener = this.themeService.onDidColorThemeChange(themeId => webview.style(themeId)); - this.contentDisposables.push(webview, linkListener, themeListener); + webview.onDidClickLink(link => this.openerService.open(link), null, this.contentDisposables); + this.themeService.onDidColorThemeChange(themeId => webview.style(themeId), null, this.contentDisposables); + this.contentDisposables.push(webview); }) .then(null, () => { const p = append(this.content, $('p'));