Convert to much simpler model
This commit is contained in:
+3
-11
@@ -44,7 +44,7 @@ import { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager';
|
||||
import { MouseZoneManager } from './ui/MouseZoneManager';
|
||||
import { AccessibilityManager } from './AccessibilityManager';
|
||||
import { ScreenDprMonitor } from './ui/ScreenDprMonitor';
|
||||
import { ITheme, IMarker, IDisposable, ITerminalAddon, ITerminalAddonConstructor } from 'xterm';
|
||||
import { ITheme, IMarker, IDisposable, ITerminalAddon } from 'xterm';
|
||||
import { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache';
|
||||
import { DomRenderer } from './renderer/dom/DomRenderer';
|
||||
import { IKeyboardEvent } from './common/Types';
|
||||
@@ -1925,16 +1925,8 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
// this.options.bellStyle === 'both';
|
||||
}
|
||||
|
||||
public loadAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
return this._addonManager.loadAddon(this, addonConstructor);
|
||||
}
|
||||
|
||||
public disposeAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): void {
|
||||
this._addonManager.disposeAddon(addonConstructor);
|
||||
}
|
||||
|
||||
public getAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
return this._addonManager.getAddon(addonConstructor);
|
||||
public loadAddon(addon: ITerminalAddon): void {
|
||||
return this._addonManager.loadAddon(this, addon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ITerminalAddonConstructor } from 'xterm';
|
||||
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon } from 'xterm';
|
||||
import { ITerminal } from '../Types';
|
||||
import { Terminal as TerminalCore } from '../Terminal';
|
||||
import * as Strings from '../Strings';
|
||||
@@ -154,14 +154,8 @@ export class Terminal implements ITerminalApi {
|
||||
public static applyAddon(addon: any): void {
|
||||
addon.apply(Terminal);
|
||||
}
|
||||
public loadAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
return this._core.loadAddon(addonConstructor);
|
||||
}
|
||||
public getAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
return this._core.getAddon(addonConstructor);
|
||||
}
|
||||
public disposeAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): void {
|
||||
this._core.disposeAddon(addonConstructor);
|
||||
public loadAddon(addon: ITerminalAddon): void {
|
||||
return this._core.loadAddon(addon);
|
||||
}
|
||||
public static get strings(): ILocalizableStrings {
|
||||
return Strings;
|
||||
|
||||
@@ -24,84 +24,27 @@ describe('AddonManager', () => {
|
||||
it('should call addon constructor', () => {
|
||||
let called = false;
|
||||
class Addon implements ITerminalAddon {
|
||||
constructor(terminal: any) {
|
||||
activate(terminal: any): void {
|
||||
assert.equal(terminal, 'foo', 'The first constructor arg should be Terminal');
|
||||
called = true;
|
||||
}
|
||||
dispose(): void { }
|
||||
}
|
||||
manager.loadAddon('foo' as any, Addon);
|
||||
manager.loadAddon('foo' as any, new Addon());
|
||||
assert.equal(called, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAddon', () => {
|
||||
it('should fetch registered addons', () => {
|
||||
class BaseAddon implements ITerminalAddon {
|
||||
constructor() { }
|
||||
dispose(): void { }
|
||||
}
|
||||
class Addon1 extends BaseAddon { }
|
||||
class Addon2 extends BaseAddon { }
|
||||
class Addon3 extends BaseAddon { }
|
||||
const addon1 = manager.loadAddon(null, Addon1);
|
||||
assert.equal(manager.getAddon(Addon1), addon1);
|
||||
assert.equal(manager.addons.length, 1);
|
||||
const addon2 = manager.loadAddon(null, Addon2);
|
||||
assert.equal(manager.getAddon(Addon1), addon1);
|
||||
assert.equal(manager.getAddon(Addon2), addon2);
|
||||
assert.equal(manager.addons.length, 2);
|
||||
const addon3 = manager.loadAddon(null, Addon3);
|
||||
assert.equal(manager.getAddon(Addon1), addon1);
|
||||
assert.equal(manager.getAddon(Addon2), addon2);
|
||||
assert.equal(manager.getAddon(Addon3), addon3);
|
||||
assert.equal(manager.addons.length, 3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('disposeAddon', () => {
|
||||
it('should dispose the loaded addon and remove it from the loaded list', () => {
|
||||
let called = 0;
|
||||
class BaseAddon implements ITerminalAddon {
|
||||
constructor() { }
|
||||
dispose(): void {
|
||||
called++;
|
||||
}
|
||||
}
|
||||
class Addon1 extends BaseAddon { }
|
||||
class Addon2 extends BaseAddon { }
|
||||
class Addon3 extends BaseAddon { }
|
||||
manager.loadAddon(null, Addon1);
|
||||
manager.loadAddon(null, Addon2);
|
||||
manager.loadAddon(null, Addon3);
|
||||
assert.equal(manager.addons.length, 3);
|
||||
manager.disposeAddon(Addon1);
|
||||
assert.equal(called, 1);
|
||||
assert.equal(manager.addons.length, 2);
|
||||
manager.disposeAddon(Addon2);
|
||||
assert.equal(called, 2);
|
||||
assert.equal(manager.addons.length, 1);
|
||||
manager.disposeAddon(Addon3);
|
||||
assert.equal(called, 3);
|
||||
assert.equal(manager.addons.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dispose', () => {
|
||||
it('should dispose all loaded addons', () => {
|
||||
let called = 0;
|
||||
class BaseAddon implements ITerminalAddon {
|
||||
constructor() { }
|
||||
dispose(): void {
|
||||
called++;
|
||||
}
|
||||
class Addon implements ITerminalAddon {
|
||||
activate(): void {}
|
||||
dispose(): void { called++; }
|
||||
}
|
||||
class Addon1 extends BaseAddon { }
|
||||
class Addon2 extends BaseAddon { }
|
||||
class Addon3 extends BaseAddon { }
|
||||
manager.loadAddon(null, Addon1);
|
||||
manager.loadAddon(null, Addon2);
|
||||
manager.loadAddon(null, Addon3);
|
||||
manager.loadAddon(null, new Addon());
|
||||
manager.loadAddon(null, new Addon());
|
||||
manager.loadAddon(null, new Addon());
|
||||
assert.equal(manager.addons.length, 3);
|
||||
manager.dispose();
|
||||
assert.equal(called, 3);
|
||||
|
||||
+12
-24
@@ -3,12 +3,12 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ITerminalAddon, ITerminalAddonConstructor, IDisposable, Terminal } from 'xterm';
|
||||
import { ITerminalAddon, IDisposable, Terminal } from 'xterm';
|
||||
|
||||
export interface ILoadedAddon {
|
||||
ctor: ITerminalAddonConstructor<ITerminalAddon>;
|
||||
instance: ITerminalAddon;
|
||||
dispose: () => void;
|
||||
isDisposed: boolean;
|
||||
}
|
||||
|
||||
export class AddonManager implements IDisposable {
|
||||
@@ -23,38 +23,25 @@ export class AddonManager implements IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
public loadAddon<T extends ITerminalAddon>(terminal: Terminal, addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
const instance = new addonConstructor(terminal);
|
||||
public loadAddon(terminal: Terminal, instance: ITerminalAddon): void {
|
||||
const loadedAddon: ILoadedAddon = {
|
||||
ctor: addonConstructor,
|
||||
instance,
|
||||
dispose: instance.dispose
|
||||
dispose: instance.dispose,
|
||||
isDisposed: false
|
||||
};
|
||||
this._addons.push(loadedAddon);
|
||||
instance.dispose = () => this._wrappedAddonDispose(loadedAddon);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public disposeAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): void {
|
||||
const match = this._addons.find(value => value.ctor === addonConstructor);
|
||||
if (!match) {
|
||||
throw new Error('Could not dispose an addon that has not been loaded');
|
||||
}
|
||||
match.instance.dispose();
|
||||
}
|
||||
|
||||
public getAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
const match = this._addons.find(value => value.ctor === addonConstructor);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
return match.instance as T;
|
||||
instance.activate(terminal);
|
||||
}
|
||||
|
||||
private _wrappedAddonDispose(loadedAddon: ILoadedAddon): void {
|
||||
if (loadedAddon.isDisposed) {
|
||||
// Do nothing if already disposed
|
||||
return;
|
||||
}
|
||||
let index = -1;
|
||||
for (let i = 0; i < this._addons.length; i++) {
|
||||
if (this._addons[i].ctor === loadedAddon.ctor) {
|
||||
if (this._addons[i] === loadedAddon) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
@@ -63,6 +50,7 @@ export class AddonManager implements IDisposable {
|
||||
throw new Error('Could not dispose an addon that has not been loaded');
|
||||
}
|
||||
loadedAddon.dispose();
|
||||
loadedAddon.isDisposed = true;
|
||||
this._addons.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuff
|
||||
import { ICircularList, XtermListener } from '../common/Types';
|
||||
import { Buffer } from '../Buffer';
|
||||
import * as Browser from '../common/Platform';
|
||||
import { ITheme, IDisposable, IMarker, ITerminalAddon, ITerminalAddonConstructor } from 'xterm';
|
||||
import { ITheme, IDisposable, IMarker, ITerminalAddon } from 'xterm';
|
||||
import { Terminal } from '../Terminal';
|
||||
import { AttributeData } from '../BufferLine';
|
||||
|
||||
@@ -20,13 +20,7 @@ export class TestTerminal extends Terminal {
|
||||
}
|
||||
|
||||
export class MockTerminal implements ITerminal {
|
||||
loadAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
disposeAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getAddon<T extends ITerminalAddon>(addonConstructor: ITerminalAddonConstructor<T>): T {
|
||||
loadAddon(addon: ITerminalAddon): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
markers: IMarker[];
|
||||
|
||||
Reference in New Issue
Block a user