Skip to content

Commit

Permalink
initial attempt
Browse files Browse the repository at this point in the history
  • Loading branch information
jerch committed Jan 10, 2025
1 parent d81b25c commit cca31f3
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 20 deletions.
25 changes: 16 additions & 9 deletions addons/addon-progress/src/ProgressAddon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
* @license MIT
*/

import type { Terminal, ITerminalAddon, IDisposable } from '@xterm/xterm';
import { Terminal, ITerminalAddon, IDisposable, EmitterCtorType, IEmitter, IEvent } from '@xterm/xterm';
import type { ProgressAddon as IProgressApi, IProgressState } from '@xterm/addon-progress';
import type { Emitter, Event } from 'vs/base/common/event';

// to use impl parts:
// in 3rd party addons
//import { EmitterAddon } from '@xterm/xterm';

Check warning on line 11 in addons/addon-progress/src/ProgressAddon.ts

View workflow job for this annotation

GitHub Actions / lint

Expected exception block, space or tab after '//' in comment
// in xtermjs repo addons
import { EmitterAddon } from 'shared/shared';


const enum ProgressType {
Expand Down Expand Up @@ -33,13 +38,18 @@ function toInt(s: string): number {
}


export class ProgressAddon implements ITerminalAddon, IProgressApi {
export class ProgressAddon extends EmitterAddon implements ITerminalAddon, IProgressApi {
private _seqHandler: IDisposable | undefined;
private _st: ProgressType = ProgressType.REMOVE;
private _pr = 0;
// HACK: This uses ! to align with the API, this should be fixed when 5283 is resolved
private _onChange!: Emitter<IProgressState>;
public onChange!: Event<IProgressState>;
private _onChange: IEmitter<IProgressState>;
public onChange: IEvent<IProgressState>;

constructor(protected readonly emitterCtor: EmitterCtorType) {

Check warning on line 48 in addons/addon-progress/src/ProgressAddon.ts

View workflow job for this annotation

GitHub Actions / lint

Parameter Property name `emitterCtor` must have one leading underscore(s)
super(emitterCtor);
this._onChange = new this.emitterCtor<IProgressState>();
this.onChange = this._onChange.event;
}

public dispose(): void {
this._seqHandler?.dispose();
Expand Down Expand Up @@ -81,9 +91,6 @@ export class ProgressAddon implements ITerminalAddon, IProgressApi {
}
return true;
});
// FIXME: borrow emitter ctor from xterm, to be changed once #5283 is resolved
this._onChange = new (terminal as any)._core._onData.constructor();
this.onChange = this._onChange!.event;
}

public get progress(): IProgressState {
Expand Down
6 changes: 6 additions & 0 deletions addons/addon-progress/src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"vs/*": [
"../../../src/vs/*"
],
"shared/*": [
"../../../src/shared/*"
],
"@xterm/addon-progress": [
"../typings/addon-progress.d.ts"
]
Expand All @@ -37,6 +40,9 @@
},
{
"path": "../../../src/vs"
},
{
"path": "../../../src/shared"
}
]
}
7 changes: 4 additions & 3 deletions addons/addon-progress/typings/addon-progress.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
* @license MIT
*/

import { Terminal, ITerminalAddon, IDisposable, IEvent } from '@xterm/xterm';
import { Terminal, ITerminalAddon, IDisposable, IEvent, EmitterCtorType } from '@xterm/xterm';
import { EmitterAddon } from 'shared/shared';

declare module '@xterm/addon-progress' {
/**
* An xterm.js addon that provides an interface for ConEmu's progress
* sequence.
*/
export class ProgressAddon implements ITerminalAddon, IDisposable {
export class ProgressAddon extends EmitterAddon implements ITerminalAddon, IDisposable {

/**
* Creates a new progress addon
*/
constructor();
constructor(emitterCtor: EmitterCtorType);

/**
* Activates the addon
Expand Down
3 changes: 2 additions & 1 deletion addons/addon-progress/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ module.exports = {
alias: {
common: path.resolve('../../out/common'),
browser: path.resolve('../../out/browser'),
vs: path.resolve('../../out/vs')
vs: path.resolve('../../out/vs'),
shared: path.resolve('../../out/shared')
}
},
output: {
Expand Down
6 changes: 3 additions & 3 deletions demo/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if ('WebAssembly' in window) {
ImageAddon = imageAddon.ImageAddon;
}

import { Terminal, ITerminalOptions, type IDisposable, type ITheme } from '@xterm/xterm';
import { Terminal, ITerminalOptions, type IDisposable, type ITheme, emitterCtor } from '@xterm/xterm';
import { AttachAddon } from '@xterm/addon-attach';
import { ClipboardAddon } from '@xterm/addon-clipboard';
import { FitAddon } from '@xterm/addon-fit';
Expand Down Expand Up @@ -279,7 +279,7 @@ function createTerminal(): void {
addons.serialize.instance = new SerializeAddon();
addons.fit.instance = new FitAddon();
addons.image.instance = new ImageAddon();
addons.progress.instance = new ProgressAddon();
addons.progress.instance = new ProgressAddon(emitterCtor);
addons.unicodeGraphemes.instance = new UnicodeGraphemesAddon();
addons.clipboard.instance = new ClipboardAddon();
try { // try to start with webgl renderer (might throw on older safari/webkit)
Expand Down Expand Up @@ -660,7 +660,7 @@ function initAddons(term: Terminal): void {
}
if (checkbox.checked) {
// HACK: Manually remove addons that cannot be changes
addon.instance = new (addon as IDemoAddon<Exclude<AddonType, 'attach'>>).ctor();
//addon.instance = new (addon as IDemoAddon<Exclude<AddonType, 'attach'>>).ctor();
try {
term.loadAddon(addon.instance);
if (name === 'webgl') {
Expand Down
19 changes: 17 additions & 2 deletions src/browser/public/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import * as Strings from 'browser/LocalizableStrings';
import { CoreBrowserTerminal as TerminalCore } from 'browser/CoreBrowserTerminal';
import { IBufferRange, ITerminal } from 'browser/Types';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, DisposableStore, toDisposable as toDisposableOrig } from 'vs/base/common/lifecycle';

Check warning on line 9 in src/browser/public/Terminal.ts

View workflow job for this annotation

GitHub Actions / lint

'DisposableStore' is defined but never used

Check warning on line 9 in src/browser/public/Terminal.ts

View workflow job for this annotation

GitHub Actions / lint

'toDisposableOrig' is defined but never used
import { ITerminalOptions } from 'common/Types';
import { AddonManager } from 'common/public/AddonManager';
import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi';
import { ParserApi } from 'common/public/ParserApi';
import { UnicodeApi } from 'common/public/UnicodeApi';
import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm';
import type { Event } from 'vs/base/common/event';
import { Emitter, type Event } from 'vs/base/common/event';

Check warning on line 16 in src/browser/public/Terminal.ts

View workflow job for this annotation

GitHub Actions / lint

'Emitter' is defined but never used

/**
* The set of options that only have an effect when set in the Terminal constructor.
Expand Down Expand Up @@ -272,3 +272,18 @@ export class Terminal extends Disposable implements ITerminalApi {
}
}
}


/**
* Expose often needed vs/* parts in addons.
* Exposed statically on the xterm package,
* so they can be used on addon ctors already.
*/
export {
DisposableStore as disposableStoreCtor,
toDisposable,
Emitter as emitterCtor,
DisposableAddon,
EmitterAddon,
DisposableEmitterAddon
} from 'shared/shared';
6 changes: 4 additions & 2 deletions src/browser/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"baseUrl": "..",
"paths": {
"common/*": [ "./common/*" ],
"vs/*": [ "./vs/*" ]
"vs/*": [ "./vs/*" ],
"shared/*": [ "./shared/*" ],
}
},
"include": [
Expand All @@ -22,6 +23,7 @@
],
"references": [
{ "path": "../common" },
{ "path": "../vs" }
{ "path": "../vs" },
{ "path": "../shared" },
]
}
44 changes: 44 additions & 0 deletions src/shared/shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright (c) 2024 The xterm.js authors. All rights reserved.
* @license MIT
*/

import { IDisposable, IDisposableStore, DisposableStoreCtorType, EmitterCtorType } from '@xterm/xterm';

export { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
export { Emitter } from 'vs/base/common/event';

export class DisposableAddon implements IDisposable {
protected readonly _store: IDisposableStore;

constructor(storeCtor: DisposableStoreCtorType) {
this._store = new storeCtor();
}

dispose(): void {
this._store.dispose();
}
}


export class EmitterAddon {
constructor(
protected readonly emitterCtor: EmitterCtorType
) {}
}


export class DisposableEmitterAddon implements IDisposable {
protected readonly _store: IDisposableStore;

constructor(
readonly storeCtor: DisposableStoreCtorType,
protected readonly emitterCtor: EmitterCtorType
) {
this._store = new storeCtor();
}

dispose(): void {
this._store.dispose();
}
}
24 changes: 24 additions & 0 deletions src/shared/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"extends": "../tsconfig-library-base",
"compilerOptions": {
"lib": [
"es2015",
"es2016.Array.Include"
],
"outDir": "../../out",
"types": [
"../../node_modules/@types/mocha"
],
"baseUrl": "..",
"paths": {
"vs/*": [ "./vs/*" ]
}
},
"include": [
"./**/*",
"../../typings/xterm.d.ts"
],
"references": [
{ "path": "../vs" }
]
}
67 changes: 67 additions & 0 deletions typings/xterm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1956,4 +1956,71 @@ declare module '@xterm/xterm' {
*/
readonly wraparoundMode: boolean;
}


/**
* Get Emitter constructor.
*/
export const emitterCtor: EmitterCtorType;

/**
* Get DisposableStore contructor.
*/
export const disposableStoreCtor: DisposableStoreCtorType;

/**
* Turn a function into a Disposable.
*/
export const toDisposable: (fn: () => void) => IDisposable;


export interface IEmitter<T> {
dispose(): void;
event: IEvent<T>;
fire(event: T): void;
hasListeners(): boolean;
}

interface IDisposableStore extends IDisposable {
/**
* `true` if this object has been disposed of.
*/
isDisposed: boolean;
/**
* Dispose of all registered disposables but do not mark this object as disposed.
*/
clear(): void;
/**
* Add a new {@link IDisposable disposable} to the collection.
*/
add<T extends IDisposable>(o: T): T;
/**
* Deletes a disposable from store and disposes of it. This will not throw or warn and proceed to dispose the
* disposable even when the disposable is not part in the store.
*/
delete<T extends IDisposable>(o: T): void;
/**
* Deletes the value from the store, but does not dispose it.
*/
deleteAndLeak<T extends IDisposable>(o: T): void;
}

export type EmitterCtorType = { new<T>(): IEmitter<T> };
export type DisposableStoreCtorType = { new(): IDisposableStore; }

export class DisposableAddon implements IDisposable {
protected readonly _store: IDisposableStore;
constructor(storeCtor: DisposableStoreCtorType);
dispose(): void;
}
export class EmitterAddon {
protected readonly emitterCtor: EmitterCtorType;
constructor(emitterCtor: EmitterCtorType);
}
export class DisposableEmitterAddon implements IDisposable {
protected readonly _store: IDisposableStore;
protected readonly emitterCtor: EmitterCtorType;
constructor(storeCtor: DisposableStoreCtorType, emitterCtor: EmitterCtorType);
dispose(): void;
}
}
1 change: 1 addition & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const config = {
common: path.resolve('./out/common'),
browser: path.resolve('./out/browser'),
vs: path.resolve('./out/vs'),
shared: path.resolve('./out/shared')
}
},
output: {
Expand Down

0 comments on commit cca31f3

Please sign in to comment.