From 99239e9160f963547dbbe040d9f12c18f939c141 Mon Sep 17 00:00:00 2001 From: Simon Lamon Date: Thu, 9 Sep 2021 18:02:40 +0000 Subject: [PATCH] Allow modifying constructor only options --- src/common/CoreTerminal.ts | 2 +- src/common/TestUtils.test.ts | 2 ++ src/common/services/OptionsService.ts | 35 +++++++++++++++++++++++++-- src/common/services/Services.ts | 1 + 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index d0f2f8f2..a5f78f66 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -86,7 +86,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { public get cols(): number { return this._bufferService.cols; } public get rows(): number { return this._bufferService.rows; } public get buffers(): IBufferSet { return this._bufferService.buffers; } - public get options(): ITerminalOptions { return this.optionsService.options; } + public get options(): ITerminalOptions { return this.optionsService.publicOptions; } constructor( options: Partial diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 1d38df21..014142ac 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -121,11 +121,13 @@ export class MockLogService implements ILogService { export class MockOptionsService implements IOptionsService { public serviceBrand: any; public options: ITerminalOptions = clone(DEFAULT_OPTIONS); + public publicOptions: ITerminalOptions = clone(DEFAULT_OPTIONS); public onOptionChange: IEvent = new EventEmitter().event; constructor(testOptions?: Partial) { if (testOptions) { for (const key of Object.keys(testOptions)) { this.options[key] = testOptions[key]; + this.publicOptions[key] = testOptions[key]; } } } diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index e1838b5d..ec1d13ad 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -72,7 +72,7 @@ export class OptionsService implements IOptionsService { public get onOptionChange(): IEvent { return this._onOptionChange.event; } constructor(options: Partial) { - this.options = { ... DEFAULT_OPTIONS }; + this.options = { ...DEFAULT_OPTIONS }; for (const key in options) { if (key in this.options) { try { @@ -88,6 +88,7 @@ export class OptionsService implements IOptionsService { for (const propName in this.options) { const privatePropName = `_${propName}`; this._options[privatePropName] = this.options[propName]; + Object.defineProperty(this.options, propName, { get: () => { if (!(propName in DEFAULT_OPTIONS)) { @@ -99,6 +100,35 @@ export class OptionsService implements IOptionsService { if (!(propName in DEFAULT_OPTIONS)) { throw new Error('No option with key "' + propName + '"'); } + + value = this._sanitizeAndValidateOption(propName, value); + // Don't fire an option change event if they didn't change + if (this._options[privatePropName] !== value) { + this._options[privatePropName] = value; + this._onOptionChange.fire(propName); + } + } + }); + } + } + + public get publicOptions(): ITerminalOptions { + const publicOptions = { ... this.options }; + for (const propName in CONSTRUCTOR_ONLY_OPTIONS) { + const privatePropName = `_${propName}`; + Object.defineProperty(publicOptions, propName, { + get: () => { + if (!(propName in DEFAULT_OPTIONS)) { + throw new Error(`No option with key "${propName}"`); + } + return this._options[privatePropName]; + }, + set: (value: any) => { + if (!(propName in DEFAULT_OPTIONS)) { + throw new Error('No option with key "' + propName + '"'); + } + // Throw an error if any constructor only option is modified + // from terminal.options if (CONSTRUCTOR_ONLY_OPTIONS.includes(propName)) { throw new Error(`Option "${propName}" can only be set in the constructor`); } @@ -112,6 +142,7 @@ export class OptionsService implements IOptionsService { } }); } + return publicOptions; } public setOption(key: string, value: any): void { @@ -138,7 +169,7 @@ export class OptionsService implements IOptionsService { break; case 'cursorWidth': value = Math.floor(value); - // Fall through for bounds check + // Fall through for bounds check case 'lineHeight': case 'tabStopWidth': if (value < 1) { diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index c5bc2900..5124260a 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -181,6 +181,7 @@ export interface IOptionsService { serviceBrand: undefined; readonly options: ITerminalOptions; + readonly publicOptions: ITerminalOptions; readonly onOptionChange: IEvent;