diff --git a/src/Interfaces.ts b/src/Interfaces.ts index da6d2727..a0d75a54 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -134,6 +134,7 @@ export interface ITerminalOptions { scrollback?: number; tabStopWidth?: number; termName?: string; + theme?: ITheme; useFlowControl?: boolean; } diff --git a/src/Terminal.ts b/src/Terminal.ts index cab25b03..15c6335a 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -82,7 +82,8 @@ const DEFAULT_OPTIONS: ITerminalOptions = { cancelEvents: false, disableStdin: false, useFlowControl: false, - tabStopWidth: 8 + tabStopWidth: 8, + theme: null // programFeatures: false, // focusKeys: false, }; @@ -320,16 +321,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT return document.activeElement === this.textarea; } - public setTheme(theme: ITheme): void { - // TODO: Allow setting of theme before renderer is ready - if (this.renderer) { - const colors = this.renderer.setTheme(theme); - if (this.viewport) { - this.viewport.onThemeChanged(colors); - } - } - } - /** * Retrieves an option's value from the terminal. * @param {string} key The option key. @@ -377,6 +368,14 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT return; } break; + case 'theme': + // If open has been called we do not want to set options.theme as the + // source of truth is owned by the renderer. + if (this.renderer) { + this._setTheme(value); + return; + } + break; case 'scrollback': if (value < 0) { console.warn(`${key} cannot be less than 0, value: ${value}`); @@ -420,7 +419,10 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT case 'bellSound': case 'bellStyle': this.syncBellSound(); break; } - this.renderer.onOptionsChanged(); + // Inform renderer of changes + if (this.renderer) { + this.renderer.onOptionsChanged(); + } } /** @@ -644,6 +646,15 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT // Measure the character size this.charMeasure.measure(this.options); + // Set the theme if it was set via setOption/constructor before open. This + // must be run after CharMeasure.measure as it depends on char dimensions. + setTimeout(() => { + if (this.options.theme) { + this._setTheme(this.options.theme); + this.options.theme = null; + } + }, 0); + // Setup loop that draws to screen this.refresh(0, this.rows - 1); @@ -655,6 +666,17 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.bindMouse(); } + /** + * Sets the theme on the renderer. The renderer must have been initialized. + * @param theme The theme to ste. + */ + private _setTheme(theme: ITheme): void { + const colors = this.renderer.setTheme(theme); + if (this.viewport) { + this.viewport.onThemeChanged(colors); + } + } + /** * Attempts to load an add-on using CommonJS or RequireJS (whichever is available). * @param {string} addon The name of the addon to load diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index eff26c9b..d98f6c5d 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -71,6 +71,11 @@ interface ITerminalOptions { * The size of tab stops in the terminal. */ tabStopWidth?: number; + + /** + * The color theme of the terminal. + */ + theme?: ITheme; } /** @@ -464,13 +469,13 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: string, value: any): void; - + setOption(key: 'theme', value: ITheme): void; /** - * Sets the theme of the terminal. - * @param theme The theme to use. + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. */ - setTheme(theme: ITheme): void; + setOption(key: string, value: any): void; /** * Tells the renderer to refresh terminal content between two rows