diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 1db5b02b6c5..67079c37c84 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -238,12 +238,12 @@ export class SwitchTerminalInstanceActionItem extends SelectActionItem { @ITerminalService private terminalService: ITerminalService ) { super(null, action, terminalService.getInstanceLabels(), terminalService.activeTerminalInstanceIndex); - this.toDispose.push(terminalService.onInstancesChanged(this.updateItems, this)); - this.toDispose.push(terminalService.onActiveInstanceChanged(this.updateItems, this)); - this.toDispose.push(terminalService.onInstanceTitleChanged(this.updateItems, this)); + this.toDispose.push(terminalService.onInstancesChanged(this._updateItems, this)); + this.toDispose.push(terminalService.onActiveInstanceChanged(this._updateItems, this)); + this.toDispose.push(terminalService.onInstanceTitleChanged(this._updateItems, this)); } - private updateItems(): void { + private _updateItems(): void { this.setOptions(this.terminalService.getInstanceLabels(), this.terminalService.activeTerminalInstanceIndex); } } diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts index 284b915b8a8..513031af2c6 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts @@ -89,29 +89,29 @@ export interface IShell { export class TerminalConfigHelper { public panelContainer: Builder; - private charMeasureElement: HTMLElement; + private _charMeasureElement: HTMLElement; public constructor( - private platform: Platform, - @IConfigurationService private configurationService: IConfigurationService) { + private _platform: Platform, + @IConfigurationService private _configurationService: IConfigurationService) { } public getTheme(baseThemeId: string): string[] { return DEFAULT_ANSI_COLORS[baseThemeId]; } - private measureFont(fontFamily: string, fontSize: number, lineHeight: number): ITerminalFont { + private _measureFont(fontFamily: string, fontSize: number, lineHeight: number): ITerminalFont { // Create charMeasureElement if it hasn't been created or if it was orphaned by its parent - if (!this.charMeasureElement || !this.charMeasureElement.parentElement) { - this.charMeasureElement = this.panelContainer.div().getHTMLElement(); + if (!this._charMeasureElement || !this._charMeasureElement.parentElement) { + this._charMeasureElement = this.panelContainer.div().getHTMLElement(); } - let style = this.charMeasureElement.style; + let style = this._charMeasureElement.style; style.display = 'block'; style.fontFamily = fontFamily; style.fontSize = fontSize + 'px'; style.height = Math.floor(lineHeight * fontSize) + 'px'; - this.charMeasureElement.innerText = 'X'; - let rect = this.charMeasureElement.getBoundingClientRect(); + this._charMeasureElement.innerText = 'X'; + let rect = this._charMeasureElement.getBoundingClientRect(); style.display = 'none'; let charWidth = Math.ceil(rect.width); let charHeight = Math.ceil(rect.height); @@ -129,8 +129,8 @@ export class TerminalConfigHelper { * terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties */ public getFont(): ITerminalFont { - let terminalConfig = this.configurationService.getConfiguration().terminal.integrated; - let editorConfig = this.configurationService.getConfiguration(); + let terminalConfig = this._configurationService.getConfiguration().terminal.integrated; + let editorConfig = this._configurationService.getConfiguration(); let fontFamily = terminalConfig.fontFamily || editorConfig.editor.fontFamily; let fontSize = this.toInteger(terminalConfig.fontSize, 0) || editorConfig.editor.fontSize; @@ -139,31 +139,31 @@ export class TerminalConfigHelper { } let lineHeight = this.toInteger(terminalConfig.lineHeight, DEFAULT_LINE_HEIGHT); - return this.measureFont(fontFamily, fontSize, lineHeight <= 0 ? DEFAULT_LINE_HEIGHT : lineHeight); + return this._measureFont(fontFamily, fontSize, lineHeight <= 0 ? DEFAULT_LINE_HEIGHT : lineHeight); } public getFontLigaturesEnabled(): boolean { - let terminalConfig = this.configurationService.getConfiguration().terminal.integrated; + let terminalConfig = this._configurationService.getConfiguration().terminal.integrated; return terminalConfig.fontLigatures; } public getCursorBlink(): boolean { - let terminalConfig = this.configurationService.getConfiguration().terminal.integrated; + let terminalConfig = this._configurationService.getConfiguration().terminal.integrated; return terminalConfig.cursorBlinking; } public getShell(): IShell { - let config = this.configurationService.getConfiguration(); + let config = this._configurationService.getConfiguration(); let shell: IShell = { executable: '', args: [] }; - if (this.platform === Platform.Windows) { + if (this._platform === Platform.Windows) { shell.executable = config.terminal.integrated.shell.windows; - } else if (this.platform === Platform.Mac) { + } else if (this._platform === Platform.Mac) { shell.executable = config.terminal.integrated.shell.osx; shell.args = config.terminal.integrated.shellArgs.osx; - } else if (this.platform === Platform.Linux) { + } else if (this._platform === Platform.Linux) { shell.executable = config.terminal.integrated.shell.linux; shell.args = config.terminal.integrated.shellArgs.linux; } @@ -171,7 +171,7 @@ export class TerminalConfigHelper { } public isSetLocaleVariables(): boolean { - let config = this.configurationService.getConfiguration(); + let config = this._configurationService.getConfiguration(); return config.terminal.integrated.setLocaleVariables; } @@ -187,7 +187,7 @@ export class TerminalConfigHelper { } public getCommandsToSkipShell(): string[] { - let config = this.configurationService.getConfiguration(); + let config = this._configurationService.getConfiguration(); return config.terminal.integrated.commandsToSkipShell; } } \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index 35ed68e82c5..67820c57f75 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -26,81 +26,88 @@ import { TabFocus } from 'vs/editor/common/config/commonEditorConfig'; import { TerminalConfigHelper, IShell } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; export class TerminalInstance implements ITerminalInstance { - private static ID_COUNTER = 1; private static EOL_REGEX = /\r?\n/g; + private static _idCounter = 1; + private _id: number; - private _title: string; + private _isExiting: boolean; + private _isVisible: boolean; private _onDisposed: Emitter; private _onTitleChanged: Emitter; + private _process: cp.ChildProcess; + private _skipTerminalKeybindings: Keybinding[]; + private _title: string; + private _toDispose: lifecycle.IDisposable[]; + private _wrapperElement: HTMLDivElement; + private _xterm: any; + private _xtermElement: HTMLDivElement; + public get id(): number { return this._id; } - public get title(): string { return this._title; } public get onClosed(): Event { return this._onDisposed.event; } 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; - private xterm: any; - private wrapperElement: HTMLDivElement; - private xtermElement: HTMLDivElement; + public get title(): string { return this._title; } public constructor( - private terminalFocusContextKey: IContextKey, - private configHelper: TerminalConfigHelper, - private container: HTMLElement, - private workspace: IWorkspace, + private _terminalFocusContextKey: IContextKey, + private _configHelper: TerminalConfigHelper, + private _container: HTMLElement, + private _workspace: IWorkspace, name: string, shell: IShell, - @IKeybindingService private keybindingService: IKeybindingService, - @IMessageService private messageService: IMessageService + @IKeybindingService private _keybindingService: IKeybindingService, + @IMessageService private _messageService: IMessageService ) { - this._id = TerminalInstance.ID_COUNTER++; + this._toDispose = []; + this._skipTerminalKeybindings = []; + this._isExiting = false; + this._isVisible = false; + this._id = TerminalInstance._idCounter++; + this._onTitleChanged = new Emitter(); this._onDisposed = new Emitter(); - this.createProcess(workspace, name, shell); - if (container) { - this.attachToElement(container); + this._createProcess(_workspace, name, shell); + + if (_container) { + this.attachToElement(_container); } } public addDisposable(disposable: lifecycle.IDisposable): void { - this.toDispose.push(disposable); + this._toDispose.push(disposable); } public attachToElement(container: HTMLElement): void { - if (this.wrapperElement) { + if (this._wrapperElement) { 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'); + this._container = container; + this._wrapperElement = document.createElement('div'); + DOM.addClass(this._wrapperElement, 'terminal-wrapper'); + this._xtermElement = document.createElement('div'); - this.xterm = xterm(); - this.xterm.open(this.xtermElement); + this._xterm = xterm(); + this._xterm.open(this._xtermElement); - this.process.on('message', (message) => { + this._process.on('message', (message) => { if (message.type === 'data') { - this.xterm.write(message.content); + this._xterm.write(message.content); } }); - this.xterm.on('data', (data) => { - this.process.send({ + this._xterm.on('data', (data) => { + this._process.send({ event: 'input', data: this.sanitizeInput(data) }); return false; }); - this.xterm.attachCustomKeydownHandler((event: KeyboardEvent) => { + this._xterm.attachCustomKeydownHandler((event: KeyboardEvent) => { // Allow the toggle tab mode keybinding to pass through the terminal so that focus can // be escaped let standardKeyboardEvent = new StandardKeyboardEvent(event); - if (this.skipTerminalKeybindings.some((k) => standardKeyboardEvent.equals(k.value))) { + if (this._skipTerminalKeybindings.some((k) => standardKeyboardEvent.equals(k.value))) { event.preventDefault(); return false; } @@ -111,7 +118,7 @@ export class TerminalInstance implements ITerminalInstance { } }); - let xtermHelper: HTMLElement = this.xterm.element.querySelector('.xterm-helpers'); + let xtermHelper: HTMLElement = this._xterm.element.querySelector('.xterm-helpers'); let focusTrap: HTMLElement = document.createElement('div'); focusTrap.setAttribute('tabindex', '0'); DOM.addClass(focusTrap, 'focus-trap'); @@ -123,63 +130,63 @@ export class TerminalInstance implements ITerminalInstance { let hidePanelElement = currentElement.querySelector('.hide-panel-action'); hidePanelElement.focus(); }); - xtermHelper.insertBefore(focusTrap, this.xterm.textarea); + xtermHelper.insertBefore(focusTrap, this._xterm.textarea); - this.toDispose.push(DOM.addDisposableListener(this.xterm.textarea, 'focus', (event: KeyboardEvent) => { - this.terminalFocusContextKey.set(true); + this._toDispose.push(DOM.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => { + this._terminalFocusContextKey.set(true); })); - this.toDispose.push(DOM.addDisposableListener(this.xterm.textarea, 'blur', (event: KeyboardEvent) => { - this.terminalFocusContextKey.reset(); + this._toDispose.push(DOM.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => { + this._terminalFocusContextKey.reset(); })); - this.toDispose.push(DOM.addDisposableListener(this.xterm.element, 'focus', (event: KeyboardEvent) => { - this.terminalFocusContextKey.set(true); + this._toDispose.push(DOM.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => { + this._terminalFocusContextKey.set(true); })); - this.toDispose.push(DOM.addDisposableListener(this.xterm.element, 'blur', (event: KeyboardEvent) => { - this.terminalFocusContextKey.reset(); + this._toDispose.push(DOM.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => { + this._terminalFocusContextKey.reset(); })); - this.wrapperElement.appendChild(this.xtermElement); - this.container.appendChild(this.wrapperElement); + this._wrapperElement.appendChild(this._xtermElement); + this._container.appendChild(this._wrapperElement); - this.layout(new Dimension(this.container.offsetWidth, this.container.offsetHeight)); - this.setVisible(this.isVisible); + this.layout(new Dimension(this._container.offsetWidth, this._container.offsetHeight)); + this.setVisible(this._isVisible); } public copySelection(): void { if (document.activeElement.classList.contains('xterm')) { document.execCommand('copy'); } else { - this.messageService.show(Severity.Warning, nls.localize('terminal.integrated.copySelection.noSelection', 'Cannot copy terminal selection when terminal does not have focus')); + this._messageService.show(Severity.Warning, nls.localize('terminal.integrated.copySelection.noSelection', 'Cannot copy terminal selection when terminal does not have focus')); } } public dispose(): void { - if (this.wrapperElement) { - this.container.removeChild(this.wrapperElement); - this.wrapperElement = null; + if (this._wrapperElement) { + this._container.removeChild(this._wrapperElement); + this._wrapperElement = null; } - if (this.xterm) { - this.xterm.destroy(); - this.xterm = null; + if (this._xterm) { + this._xterm.destroy(); + this._xterm = null; } - if (this.process) { - if (this.process.connected) { - this.process.disconnect(); - this.process.kill(); + if (this._process) { + if (this._process.connected) { + this._process.disconnect(); + this._process.kill(); } - this.process = null; + this._process = null; } this._onDisposed.fire(this); - this.toDispose = lifecycle.dispose(this.toDispose); + this._toDispose = lifecycle.dispose(this._toDispose); } public focus(force?: boolean): void { - if (!this.xterm) { + if (!this._xterm) { return; } let text = window.getSelection().toString(); if (!text || force) { - this.xterm.focus(); + this._xterm.focus(); } } @@ -192,65 +199,65 @@ export class TerminalInstance implements ITerminalInstance { if (addNewLine && text.substr(text.length - os.EOL.length) !== os.EOL) { text += os.EOL; } - this.process.send({ + this._process.send({ event: 'input', data: text }); } public setVisible(visible: boolean): void { - this.isVisible = visible; - if (this.wrapperElement) { - DOM.toggleClass(this.wrapperElement, 'active', visible); + this._isVisible = visible; + if (this._wrapperElement) { + DOM.toggleClass(this._wrapperElement, 'active', visible); } } public scrollDown(): void { - this.xterm.scrollDisp(1); + this._xterm.scrollDisp(1); } public scrollUp(): void { - this.xterm.scrollDisp(-1); + this._xterm.scrollDisp(-1); } private sanitizeInput(data: any) { return typeof data === 'string' ? data.replace(TerminalInstance.EOL_REGEX, os.EOL) : data; } - private createProcess(workspace: IWorkspace, name: string, shell: IShell) { - let locale = this.configHelper.isSetLocaleVariables() ? platform.locale : undefined; + private _createProcess(workspace: IWorkspace, name: string, shell: IShell) { + let locale = this._configHelper.isSetLocaleVariables() ? platform.locale : undefined; if (!shell.executable) { - shell = this.configHelper.getShell(); + shell = this._configHelper.getShell(); } let env = TerminalInstance.createTerminalEnv(process.env, shell, workspace, locale); this._title = name ? name : ''; - this.process = cp.fork('./terminalProcess', [], { + this._process = cp.fork('./terminalProcess', [], { env: env, cwd: URI.parse(path.dirname(require.toUrl('./terminalProcess'))).fsPath }); if (!name) { // Only listen for process title changes when a name is not provided - this.process.on('message', (message) => { + this._process.on('message', (message) => { if (message.type === 'title') { this._title = message.content ? message.content : ''; this._onTitleChanged.fire(this._title); } }); } - this.process.on('exit', (exitCode) => { + this._process.on('exit', (exitCode) => { // Prevent dispose functions being triggered multiple times - if (!this.isExiting) { - this.isExiting = true; + if (!this._isExiting) { + this._isExiting = true; this.dispose(); if (exitCode) { - this.messageService.show(Severity.Error, nls.localize('terminal.integrated.exitedWithCode', 'The terminal process terminated with exit code: {0}', exitCode)); + this._messageService.show(Severity.Error, nls.localize('terminal.integrated.exitedWithCode', 'The terminal process terminated with exit code: {0}', exitCode)); } } }); } public static createTerminalEnv(parentEnv: IStringDictionary, shell: IShell, workspace: IWorkspace, locale?: string): IStringDictionary { - let env = TerminalInstance.cloneEnv(parentEnv); + let env = TerminalInstance._cloneEnv(parentEnv); env['PTYPID'] = process.pid.toString(); env['PTYSHELL'] = shell.executable; if (shell.args) { @@ -258,14 +265,14 @@ export class TerminalInstance implements ITerminalInstance { env[`PTYSHELLARG${i}`] = arg; }); } - env['PTYCWD'] = TerminalInstance.sanitizeCwd(workspace ? workspace.resource.fsPath : os.homedir()); + env['PTYCWD'] = TerminalInstance._sanitizeCwd(workspace ? workspace.resource.fsPath : os.homedir()); if (locale) { - env['LANG'] = TerminalInstance.getLangEnvVariable(locale); + env['LANG'] = TerminalInstance._getLangEnvVariable(locale); } return env; } - private static sanitizeCwd(cwd: string) { + private static _sanitizeCwd(cwd: string) { // Make the drive letter uppercase on Windows (see #9448) if (platform.platform === platform.Platform.Windows && cwd && cwd[1] === ':') { return cwd[0].toUpperCase() + cwd.substr(1); @@ -273,7 +280,7 @@ export class TerminalInstance implements ITerminalInstance { return cwd; } - private static cloneEnv(env: IStringDictionary): IStringDictionary { + private static _cloneEnv(env: IStringDictionary): IStringDictionary { let newEnv: IStringDictionary = Object.create(null); Object.keys(env).forEach((key) => { newEnv[key] = env[key]; @@ -281,7 +288,7 @@ export class TerminalInstance implements ITerminalInstance { return newEnv; } - private static getLangEnvVariable(locale: string) { + private static _getLangEnvVariable(locale: string) { const parts = locale.split('-'); const n = parts.length; if (n > 1) { @@ -291,22 +298,22 @@ export class TerminalInstance implements ITerminalInstance { } public setCursorBlink(blink: boolean): void { - if (this.xterm && this.xterm.cursorBlink !== blink) { - this.xterm.cursorBlink = blink; - this.xterm.refresh(0, this.xterm.rows - 1); + if (this._xterm && this._xterm.cursorBlink !== blink) { + this._xterm.cursorBlink = blink; + this._xterm.refresh(0, this._xterm.rows - 1); } } public setCommandsToSkipShell(commands: string[]): void { - this.skipTerminalKeybindings = commands.map((c) => { - return this.keybindingService.lookupKeybindings(c); + this._skipTerminalKeybindings = commands.map((c) => { + return this._keybindingService.lookupKeybindings(c); }).reduce((prev, curr) => { return prev.concat(curr); }); } public layout(dimension: Dimension): void { - let font = this.configHelper.getFont(); + let font = this._configHelper.getFont(); if (!font || !font.charWidth || !font.charHeight) { return; } @@ -317,12 +324,12 @@ export class TerminalInstance implements ITerminalInstance { let innerWidth = dimension.width - leftPadding; let cols = Math.floor(innerWidth / font.charWidth); let rows = Math.floor(dimension.height / font.charHeight); - if (this.xterm) { - this.xterm.resize(cols, rows); - this.xterm.element.style.width = innerWidth + 'px'; + if (this._xterm) { + this._xterm.resize(cols, rows); + this._xterm.element.style.width = innerWidth + 'px'; } - if (this.process.connected) { - this.process.send({ + if (this._process.connected) { + this._process.send({ event: 'resize', cols: cols, rows: rows diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 333101d492d..50cf92b2233 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -27,53 +27,54 @@ import { getBaseThemeId } from 'vs/platform/theme/common/themes'; export class TerminalPanel extends Panel { - private toDispose: lifecycle.IDisposable[] = []; - - private actions: IAction[]; - private contextMenuActions: IAction[]; - private parentDomElement: HTMLElement; - private terminalContainer: HTMLElement; - private currentBaseThemeId: string; - private themeStyleElement: HTMLElement; - private fontStyleElement: HTMLElement; - private font: ITerminalFont; + private _actions: IAction[]; + private _contextMenuActions: IAction[]; + private _currentBaseThemeId: string; + private _font: ITerminalFont; + private _fontStyleElement: HTMLElement; + private _parentDomElement: HTMLElement; + private _terminalContainer: HTMLElement; + private _themeStyleElement: HTMLElement; + private _toDispose: lifecycle.IDisposable[]; constructor( - @IConfigurationService private configurationService: IConfigurationService, - @IContextMenuService private contextMenuService: IContextMenuService, - @IInstantiationService private instantiationService: IInstantiationService, - @IKeybindingService private keybindingService: IKeybindingService, - @ITelemetryService telemetryService: ITelemetryService, - @ITerminalService private terminalService: ITerminalService, - @IThemeService private themeService: IThemeService + @IConfigurationService private _configurationService: IConfigurationService, + @IContextMenuService private _contextMenuService: IContextMenuService, + @IInstantiationService private _instantiationService: IInstantiationService, + @IKeybindingService private _keybindingService: IKeybindingService, + @ITerminalService private _terminalService: ITerminalService, + @IThemeService private _themeService: IThemeService, + @ITelemetryService telemetryService: ITelemetryService ) { super(TERMINAL_PANEL_ID, telemetryService); + + this._toDispose = []; } public create(parent: Builder): TPromise { super.create(parent); - this.parentDomElement = parent.getHTMLElement(); - DOM.addClass(this.parentDomElement, 'integrated-terminal'); - this.themeStyleElement = document.createElement('style'); - this.fontStyleElement = document.createElement('style'); + this._parentDomElement = parent.getHTMLElement(); + DOM.addClass(this._parentDomElement, 'integrated-terminal'); + this._themeStyleElement = document.createElement('style'); + this._fontStyleElement = document.createElement('style'); - this.terminalContainer = document.createElement('div'); - DOM.addClass(this.terminalContainer, 'terminal-outer-container'); - this.parentDomElement.appendChild(this.themeStyleElement); - this.parentDomElement.appendChild(this.fontStyleElement); - this.parentDomElement.appendChild(this.terminalContainer); + this._terminalContainer = document.createElement('div'); + DOM.addClass(this._terminalContainer, 'terminal-outer-container'); + this._parentDomElement.appendChild(this._themeStyleElement); + this._parentDomElement.appendChild(this._fontStyleElement); + this._parentDomElement.appendChild(this._terminalContainer); - this.attachEventListeners(); + this._attachEventListeners(); - this.terminalService.setContainers(this.getContainer(), this.terminalContainer); + this._terminalService.setContainers(this.getContainer(), this._terminalContainer); - this.toDispose.push(this.themeService.onDidColorThemeChange(this.updateTheme.bind(this))); - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(this.updateConfig.bind(this))); - this.updateTheme(); - this.updateConfig(); + this._toDispose.push(this._themeService.onDidColorThemeChange(this._updateTheme.bind(this))); + this._toDispose.push(this._configurationService.onDidUpdateConfiguration(this._updateConfig.bind(this))); + this._updateTheme(); + this._updateConfig(); // Force another layout (first is setContainers) since config has changed - this.layout(new Dimension(this.terminalContainer.offsetWidth, this.terminalContainer.offsetHeight)); + this.layout(new Dimension(this._terminalContainer.offsetWidth, this._terminalContainer.offsetHeight)); return TPromise.as(void 0); } @@ -81,21 +82,21 @@ export class TerminalPanel extends Panel { if (!dimension) { return; } - this.terminalService.terminalInstances.forEach((t) => { + this._terminalService.terminalInstances.forEach((t) => { t.layout(dimension); }); } public setVisible(visible: boolean): TPromise { if (visible) { - if (this.terminalService.terminalInstances.length > 0) { - this.updateConfig(); - this.updateTheme(); + if (this._terminalService.terminalInstances.length > 0) { + this._updateConfig(); + this._updateTheme(); } else { return super.setVisible(visible).then(() => { - this.terminalService.createInstance(); - this.updateConfig(); - this.updateTheme(); + this._terminalService.createInstance(); + this._updateConfig(); + this._updateTheme(); }); } } @@ -103,66 +104,66 @@ export class TerminalPanel extends Panel { } public getActions(): IAction[] { - if (!this.actions) { - this.actions = [ - this.instantiationService.createInstance(SwitchTerminalInstanceAction, SwitchTerminalInstanceAction.ID, SwitchTerminalInstanceAction.LABEL), - this.instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.PANEL_LABEL), - this.instantiationService.createInstance(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.PANEL_LABEL) + if (!this._actions) { + this._actions = [ + this._instantiationService.createInstance(SwitchTerminalInstanceAction, SwitchTerminalInstanceAction.ID, SwitchTerminalInstanceAction.LABEL), + this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.PANEL_LABEL), + this._instantiationService.createInstance(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.PANEL_LABEL) ]; - this.actions.forEach(a => { - this.toDispose.push(a); + this._actions.forEach(a => { + this._toDispose.push(a); }); } - return this.actions; + return this._actions; } - private getContextMenuActions(): IAction[] { - if (!this.contextMenuActions) { - this.contextMenuActions = [ - this.instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, nls.localize('createNewTerminal', "New Terminal")), + private _getContextMenuActions(): IAction[] { + if (!this._contextMenuActions) { + this._contextMenuActions = [ + this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, nls.localize('createNewTerminal', "New Terminal")), new Separator(), - this.instantiationService.createInstance(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, nls.localize('copy', "Copy")), - this.instantiationService.createInstance(TerminalPasteAction, TerminalPasteAction.ID, nls.localize('paste', "Paste")) + this._instantiationService.createInstance(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, nls.localize('copy', "Copy")), + this._instantiationService.createInstance(TerminalPasteAction, TerminalPasteAction.ID, nls.localize('paste', "Paste")) ]; - this.contextMenuActions.forEach(a => { - this.toDispose.push(a); + this._contextMenuActions.forEach(a => { + this._toDispose.push(a); }); } - return this.contextMenuActions; + return this._contextMenuActions; } public getActionItem(action: Action): IActionItem { if (action.id === SwitchTerminalInstanceAction.ID) { - return this.instantiationService.createInstance(SwitchTerminalInstanceActionItem, action); + return this._instantiationService.createInstance(SwitchTerminalInstanceActionItem, action); } return super.getActionItem(action); } - private attachEventListeners(): void { - this.toDispose.push(DOM.addDisposableListener(this.parentDomElement, 'mousedown', (event: MouseEvent) => { - if (this.terminalService.terminalInstances.length === 0) { + private _attachEventListeners(): void { + this._toDispose.push(DOM.addDisposableListener(this._parentDomElement, 'mousedown', (event: MouseEvent) => { + if (this._terminalService.terminalInstances.length === 0) { return; } if (event.which === 2 && platform.isLinux) { // Drop selection and focus terminal on Linux to enable middle button paste when click // occurs on the selection itself. - this.terminalService.getActiveInstance().focus(); + this._terminalService.getActiveInstance().focus(); } else if (event.which === 3) { // Trigger the context menu on right click - let anchor: HTMLElement | { x: number, y: number } = this.parentDomElement; + let anchor: HTMLElement | { x: number, y: number } = this._parentDomElement; if (event instanceof MouseEvent) { const standardEvent = new StandardMouseEvent(event); anchor = { x: standardEvent.posx, y: standardEvent.posy }; } - this.contextMenuService.showContextMenu({ + this._contextMenuService.showContextMenu({ getAnchor: () => anchor, - getActions: () => TPromise.as(this.getContextMenuActions()), - getActionsContext: () => this.parentDomElement, + getActions: () => TPromise.as(this._getContextMenuActions()), + getActionsContext: () => this._parentDomElement, getKeyBinding: (action) => { - const opts = this.keybindingService.lookupKeybindings(action.id); + const opts = this._keybindingService.lookupKeybindings(action.id); if (opts.length > 0) { return opts[0]; // only take the first one } @@ -171,16 +172,16 @@ export class TerminalPanel extends Panel { }); } })); - this.toDispose.push(DOM.addDisposableListener(this.parentDomElement, 'mouseup', (event) => { - if (this.terminalService.terminalInstances.length === 0) { + this._toDispose.push(DOM.addDisposableListener(this._parentDomElement, 'mouseup', (event) => { + if (this._terminalService.terminalInstances.length === 0) { return; } if (event.which !== 3) { - this.terminalService.getActiveInstance().focus(); + this._terminalService.getActiveInstance().focus(); } })); - this.toDispose.push(DOM.addDisposableListener(this.parentDomElement, 'keyup', (event: KeyboardEvent) => { + this._toDispose.push(DOM.addDisposableListener(this._parentDomElement, 'keyup', (event: KeyboardEvent) => { if (event.keyCode === 27) { // Keep terminal open on escape event.stopPropagation(); @@ -188,65 +189,65 @@ export class TerminalPanel extends Panel { })); } - private updateTheme(themeId?: string): void { + private _updateTheme(themeId?: string): void { if (!themeId) { - themeId = this.themeService.getColorTheme(); + themeId = this._themeService.getColorTheme(); } let baseThemeId = getBaseThemeId(themeId); - if (baseThemeId === this.currentBaseThemeId) { + if (baseThemeId === this._currentBaseThemeId) { return; } - this.currentBaseThemeId = baseThemeId; + this._currentBaseThemeId = baseThemeId; - let theme = this.terminalService.configHelper.getTheme(baseThemeId); + let theme = this._terminalService.configHelper.getTheme(baseThemeId); let css = ''; theme.forEach((color: string, index: number) => { - let rgba = this.convertHexCssColorToRgba(color, 0.996); + let rgba = this._convertHexCssColorToRgba(color, 0.996); css += `.monaco-workbench .panel.integrated-terminal .xterm .xterm-color-${index} { color: ${color}; }` + `.monaco-workbench .panel.integrated-terminal .xterm .xterm-color-${index}::selection { background-color: ${rgba}; }` + `.monaco-workbench .panel.integrated-terminal .xterm .xterm-bg-color-${index} { background-color: ${color}; }` + `.monaco-workbench .panel.integrated-terminal .xterm .xterm-bg-color-${index}::selection { color: ${color}; }`; }); - this.themeStyleElement.innerHTML = css; + this._themeStyleElement.innerHTML = css; } /** * Converts a CSS hex color (#rrggbb) to a CSS rgba color (rgba(r, g, b, a)). */ - private convertHexCssColorToRgba(hex: string, alpha: number): string { + private _convertHexCssColorToRgba(hex: string, alpha: number): string { let r = parseInt(hex.substr(1, 2), 16); let g = parseInt(hex.substr(3, 2), 16); let b = parseInt(hex.substr(5, 2), 16); return `rgba(${r}, ${g}, ${b}, ${alpha})`; } - private updateConfig(): void { - this.updateFont(); - this.updateCursorBlink(); - this.updateCommandsToSkipShell(); + private _updateConfig(): void { + this._updateFont(); + this._updateCursorBlink(); + this._updateCommandsToSkipShell(); } - private updateFont(): void { - if (this.terminalService.terminalInstances.length === 0) { + private _updateFont(): void { + if (this._terminalService.terminalInstances.length === 0) { return; } - let newFont = this.terminalService.configHelper.getFont(); - DOM.toggleClass(this.parentDomElement, 'enable-ligatures', this.terminalService.configHelper.getFontLigaturesEnabled()); - if (!this.font || this.fontsDiffer(this.font, newFont)) { - this.fontStyleElement.innerHTML = '.monaco-workbench .panel.integrated-terminal .xterm {' + + let newFont = this._terminalService.configHelper.getFont(); + DOM.toggleClass(this._parentDomElement, 'enable-ligatures', this._terminalService.configHelper.getFontLigaturesEnabled()); + if (!this._font || this._fontsDiffer(this._font, newFont)) { + this._fontStyleElement.innerHTML = '.monaco-workbench .panel.integrated-terminal .xterm {' + `font-family: ${newFont.fontFamily};` + `font-size: ${newFont.fontSize};` + `line-height: ${newFont.lineHeight};` + '}'; - this.font = newFont; + this._font = newFont; } - this.layout(new Dimension(this.parentDomElement.offsetWidth, this.parentDomElement.offsetHeight)); + this.layout(new Dimension(this._parentDomElement.offsetWidth, this._parentDomElement.offsetHeight)); } - private fontsDiffer(a: ITerminalFont, b: ITerminalFont): boolean { + private _fontsDiffer(a: ITerminalFont, b: ITerminalFont): boolean { return a.charHeight !== b.charHeight || a.charWidth !== b.charWidth || a.fontFamily !== b.fontFamily || @@ -254,15 +255,15 @@ export class TerminalPanel extends Panel { a.lineHeight !== b.lineHeight; } - private updateCursorBlink(): void { - this.terminalService.terminalInstances.forEach((instance) => { - instance.setCursorBlink(this.terminalService.configHelper.getCursorBlink()); + private _updateCursorBlink(): void { + this._terminalService.terminalInstances.forEach((instance) => { + instance.setCursorBlink(this._terminalService.configHelper.getCursorBlink()); }); } - private updateCommandsToSkipShell(): void { - this.terminalService.terminalInstances.forEach((instance) => { - instance.setCommandsToSkipShell(this.terminalService.configHelper.getCommandsToSkipShell()); + private _updateCommandsToSkipShell(): void { + this._terminalService.terminalInstances.forEach((instance) => { + instance.setCommandsToSkipShell(this._terminalService.configHelper.getCommandsToSkipShell()); }); } } diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index cbcc8204db8..e5077545167 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -20,13 +20,16 @@ import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/t export class TerminalService implements ITerminalService { public _serviceBrand: any; - private _activeTerminalInstanceIndex: number = 0; + private _activeTerminalInstanceIndex: number; private _configHelper: TerminalConfigHelper; private _onActiveInstanceChanged: Emitter; private _onInstanceDisposed: Emitter; private _onInstanceTitleChanged: Emitter; private _onInstancesChanged: Emitter; - private _terminalInstances: ITerminalInstance[] = []; + private _terminalContainer: HTMLElement; + private _terminalFocusContextKey: IContextKey; + private _terminalInstances: ITerminalInstance[]; + public get activeTerminalInstanceIndex(): number { return this._activeTerminalInstanceIndex; } public get configHelper(): TerminalConfigHelper { return this._configHelper; } public get onActiveInstanceChanged(): Event { return this._onActiveInstanceChanged.event; } @@ -35,24 +38,25 @@ export class TerminalService implements ITerminalService { public get onInstancesChanged(): Event { return this._onInstancesChanged.event; } public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } - private terminalContainer: HTMLElement; - private terminalFocusContextKey: IContextKey; - constructor( - @IConfigurationService private configurationService: IConfigurationService, - @IContextKeyService private contextKeyService: IContextKeyService, - @IInstantiationService private instantiationService: IInstantiationService, - @IPanelService private panelService: IPanelService, - @IPartService private partService: IPartService, - @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService + @IConfigurationService private _configurationService: IConfigurationService, + @IContextKeyService private _contextKeyService: IContextKeyService, + @IInstantiationService private _instantiationService: IInstantiationService, + @IPanelService private _panelService: IPanelService, + @IPartService private _partService: IPartService, + @IWorkspaceContextService private _workspaceContextService: IWorkspaceContextService ) { + this._terminalInstances = []; + this._activeTerminalInstanceIndex = 0; + this._onActiveInstanceChanged = new Emitter(); this._onInstanceDisposed = new Emitter(); this._onInstancesChanged = new Emitter(); this._onInstanceTitleChanged = new Emitter(); - this.terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this.contextKeyService); - this._configHelper = this.instantiationService.createInstance(TerminalConfigHelper, platform.platform); - this.onInstanceDisposed((terminalInstance) => { this.removeInstance(terminalInstance); }); + + this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService); + this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper, platform.platform); + this.onInstanceDisposed((terminalInstance) => { this._removeInstance(terminalInstance); }); } public createInstance(name?: string, shellPath?: string, shellArgs?: string[]): ITerminalInstance { @@ -60,11 +64,11 @@ export class TerminalService implements ITerminalService { executable: shellPath, args: shellArgs }; - let terminalInstance = this.instantiationService.createInstance(TerminalInstance, - this.terminalFocusContextKey, + let terminalInstance = this._instantiationService.createInstance(TerminalInstance, + this._terminalFocusContextKey, this._configHelper, - this.terminalContainer, - this.workspaceContextService.getWorkspace(), + this._terminalContainer, + this._workspaceContextService.getWorkspace(), name, shell); terminalInstance.addDisposable(terminalInstance.onTitleChanged(this._onInstanceTitleChanged.fire, this._onInstanceTitleChanged)); @@ -82,7 +86,7 @@ export class TerminalService implements ITerminalService { return this._terminalInstances.map((instance, index) => `${index + 1}: ${instance.title}`); } - private removeInstance(terminalInstance: ITerminalInstance): void { + private _removeInstance(terminalInstance: ITerminalInstance): void { let index = this.terminalInstances.indexOf(terminalInstance); let wasActiveInstance = terminalInstance === this.getActiveInstance(); if (index !== -1) { @@ -109,11 +113,11 @@ export class TerminalService implements ITerminalService { } public getInstanceFromId(terminalId: number): ITerminalInstance { - return this.terminalInstances[this.getIndexFromId(terminalId)]; + return this.terminalInstances[this._getIndexFromId(terminalId)]; } public setActiveInstance(terminalInstance: ITerminalInstance): void { - this.setActiveInstanceByIndex(this.getIndexFromId(terminalInstance.id)); + this.setActiveInstanceByIndex(this._getIndexFromId(terminalInstance.id)); } public setActiveInstanceByIndex(terminalIndex: number): void { @@ -148,17 +152,17 @@ export class TerminalService implements ITerminalService { public setContainers(panelContainer: Builder, terminalContainer: HTMLElement): void { this._configHelper.panelContainer = panelContainer; - this.terminalContainer = terminalContainer; + this._terminalContainer = terminalContainer; this._terminalInstances.forEach(terminalInstance => { - terminalInstance.attachToElement(this.terminalContainer); + terminalInstance.attachToElement(this._terminalContainer); }); } public showPanel(focus?: boolean): TPromise { return new TPromise((complete) => { - let panel = this.panelService.getActivePanel(); + let panel = this._panelService.getActivePanel(); if (!panel || panel.getId() !== TERMINAL_PANEL_ID) { - return this.panelService.openPanel(TERMINAL_PANEL_ID, focus).then(() => { + return this._panelService.openPanel(TERMINAL_PANEL_ID, focus).then(() => { if (focus) { this.getActiveInstance().focus(true); } @@ -174,22 +178,22 @@ export class TerminalService implements ITerminalService { } public hidePanel(): void { - const panel = this.panelService.getActivePanel(); + const panel = this._panelService.getActivePanel(); if (panel && panel.getId() === TERMINAL_PANEL_ID) { - this.partService.setPanelHidden(true); + this._partService.setPanelHidden(true); } } public togglePanel(): TPromise { - const panel = this.panelService.getActivePanel(); + const panel = this._panelService.getActivePanel(); if (panel && panel.getId() === TERMINAL_PANEL_ID) { - this.partService.setPanelHidden(true); + this._partService.setPanelHidden(true); return TPromise.as(null); } this.showPanel(true); } - private getIndexFromId(terminalId: number): number { + private _getIndexFromId(terminalId: number): number { let terminalIndex = -1; this.terminalInstances.forEach((terminalInstance, i) => { if (terminalInstance.id === terminalId) {