@xterm/xterm 5.4.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +235 -0
  3. package/css/xterm.css +209 -0
  4. package/lib/xterm.js +2 -0
  5. package/lib/xterm.js.map +1 -0
  6. package/package.json +101 -0
  7. package/src/browser/AccessibilityManager.ts +278 -0
  8. package/src/browser/Clipboard.ts +93 -0
  9. package/src/browser/ColorContrastCache.ts +34 -0
  10. package/src/browser/Lifecycle.ts +33 -0
  11. package/src/browser/Linkifier2.ts +416 -0
  12. package/src/browser/LocalizableStrings.ts +12 -0
  13. package/src/browser/OscLinkProvider.ts +128 -0
  14. package/src/browser/RenderDebouncer.ts +83 -0
  15. package/src/browser/Terminal.ts +1317 -0
  16. package/src/browser/TimeBasedDebouncer.ts +86 -0
  17. package/src/browser/Types.d.ts +181 -0
  18. package/src/browser/Viewport.ts +401 -0
  19. package/src/browser/decorations/BufferDecorationRenderer.ts +134 -0
  20. package/src/browser/decorations/ColorZoneStore.ts +117 -0
  21. package/src/browser/decorations/OverviewRulerRenderer.ts +218 -0
  22. package/src/browser/input/CompositionHelper.ts +246 -0
  23. package/src/browser/input/Mouse.ts +54 -0
  24. package/src/browser/input/MoveToCell.ts +249 -0
  25. package/src/browser/public/Terminal.ts +260 -0
  26. package/src/browser/renderer/dom/DomRenderer.ts +509 -0
  27. package/src/browser/renderer/dom/DomRendererRowFactory.ts +526 -0
  28. package/src/browser/renderer/dom/WidthCache.ts +160 -0
  29. package/src/browser/renderer/shared/CellColorResolver.ts +137 -0
  30. package/src/browser/renderer/shared/CharAtlasCache.ts +96 -0
  31. package/src/browser/renderer/shared/CharAtlasUtils.ts +75 -0
  32. package/src/browser/renderer/shared/Constants.ts +14 -0
  33. package/src/browser/renderer/shared/CursorBlinkStateManager.ts +146 -0
  34. package/src/browser/renderer/shared/CustomGlyphs.ts +687 -0
  35. package/src/browser/renderer/shared/DevicePixelObserver.ts +41 -0
  36. package/src/browser/renderer/shared/README.md +1 -0
  37. package/src/browser/renderer/shared/RendererUtils.ts +58 -0
  38. package/src/browser/renderer/shared/SelectionRenderModel.ts +91 -0
  39. package/src/browser/renderer/shared/TextureAtlas.ts +1082 -0
  40. package/src/browser/renderer/shared/Types.d.ts +173 -0
  41. package/src/browser/selection/SelectionModel.ts +144 -0
  42. package/src/browser/selection/Types.d.ts +15 -0
  43. package/src/browser/services/CharSizeService.ts +102 -0
  44. package/src/browser/services/CharacterJoinerService.ts +339 -0
  45. package/src/browser/services/CoreBrowserService.ts +137 -0
  46. package/src/browser/services/MouseService.ts +46 -0
  47. package/src/browser/services/RenderService.ts +279 -0
  48. package/src/browser/services/SelectionService.ts +1031 -0
  49. package/src/browser/services/Services.ts +147 -0
  50. package/src/browser/services/ThemeService.ts +237 -0
  51. package/src/common/CircularList.ts +241 -0
  52. package/src/common/Clone.ts +23 -0
  53. package/src/common/Color.ts +357 -0
  54. package/src/common/CoreTerminal.ts +284 -0
  55. package/src/common/EventEmitter.ts +78 -0
  56. package/src/common/InputHandler.ts +3461 -0
  57. package/src/common/Lifecycle.ts +108 -0
  58. package/src/common/MultiKeyMap.ts +42 -0
  59. package/src/common/Platform.ts +44 -0
  60. package/src/common/SortedList.ts +118 -0
  61. package/src/common/TaskQueue.ts +166 -0
  62. package/src/common/TypedArrayUtils.ts +17 -0
  63. package/src/common/Types.d.ts +553 -0
  64. package/src/common/WindowsMode.ts +27 -0
  65. package/src/common/buffer/AttributeData.ts +196 -0
  66. package/src/common/buffer/Buffer.ts +654 -0
  67. package/src/common/buffer/BufferLine.ts +524 -0
  68. package/src/common/buffer/BufferRange.ts +13 -0
  69. package/src/common/buffer/BufferReflow.ts +223 -0
  70. package/src/common/buffer/BufferSet.ts +134 -0
  71. package/src/common/buffer/CellData.ts +94 -0
  72. package/src/common/buffer/Constants.ts +149 -0
  73. package/src/common/buffer/Marker.ts +43 -0
  74. package/src/common/buffer/Types.d.ts +52 -0
  75. package/src/common/data/Charsets.ts +256 -0
  76. package/src/common/data/EscapeSequences.ts +153 -0
  77. package/src/common/input/Keyboard.ts +398 -0
  78. package/src/common/input/TextDecoder.ts +346 -0
  79. package/src/common/input/UnicodeV6.ts +145 -0
  80. package/src/common/input/WriteBuffer.ts +246 -0
  81. package/src/common/input/XParseColor.ts +80 -0
  82. package/src/common/parser/Constants.ts +58 -0
  83. package/src/common/parser/DcsParser.ts +192 -0
  84. package/src/common/parser/EscapeSequenceParser.ts +792 -0
  85. package/src/common/parser/OscParser.ts +238 -0
  86. package/src/common/parser/Params.ts +229 -0
  87. package/src/common/parser/Types.d.ts +275 -0
  88. package/src/common/public/AddonManager.ts +53 -0
  89. package/src/common/public/BufferApiView.ts +35 -0
  90. package/src/common/public/BufferLineApiView.ts +29 -0
  91. package/src/common/public/BufferNamespaceApi.ts +36 -0
  92. package/src/common/public/ParserApi.ts +37 -0
  93. package/src/common/public/UnicodeApi.ts +27 -0
  94. package/src/common/services/BufferService.ts +151 -0
  95. package/src/common/services/CharsetService.ts +34 -0
  96. package/src/common/services/CoreMouseService.ts +318 -0
  97. package/src/common/services/CoreService.ts +87 -0
  98. package/src/common/services/DecorationService.ts +140 -0
  99. package/src/common/services/InstantiationService.ts +85 -0
  100. package/src/common/services/LogService.ts +124 -0
  101. package/src/common/services/OptionsService.ts +202 -0
  102. package/src/common/services/OscLinkService.ts +115 -0
  103. package/src/common/services/ServiceRegistry.ts +49 -0
  104. package/src/common/services/Services.ts +373 -0
  105. package/src/common/services/UnicodeService.ts +111 -0
  106. package/src/headless/Terminal.ts +136 -0
  107. package/src/headless/public/Terminal.ts +195 -0
  108. package/typings/xterm.d.ts +1857 -0
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+ import { IBufferService, ICoreService, ICoreMouseService } from 'common/services/Services';
6
+ import { EventEmitter } from 'common/EventEmitter';
7
+ import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';
8
+ import { Disposable } from 'common/Lifecycle';
9
+
10
+ /**
11
+ * Supported default protocols.
12
+ */
13
+ const DEFAULT_PROTOCOLS: { [key: string]: ICoreMouseProtocol } = {
14
+ /**
15
+ * NONE
16
+ * Events: none
17
+ * Modifiers: none
18
+ */
19
+ NONE: {
20
+ events: CoreMouseEventType.NONE,
21
+ restrict: () => false
22
+ },
23
+ /**
24
+ * X10
25
+ * Events: mousedown
26
+ * Modifiers: none
27
+ */
28
+ X10: {
29
+ events: CoreMouseEventType.DOWN,
30
+ restrict: (e: ICoreMouseEvent) => {
31
+ // no wheel, no move, no up
32
+ if (e.button === CoreMouseButton.WHEEL || e.action !== CoreMouseAction.DOWN) {
33
+ return false;
34
+ }
35
+ // no modifiers
36
+ e.ctrl = false;
37
+ e.alt = false;
38
+ e.shift = false;
39
+ return true;
40
+ }
41
+ },
42
+ /**
43
+ * VT200
44
+ * Events: mousedown / mouseup / wheel
45
+ * Modifiers: all
46
+ */
47
+ VT200: {
48
+ events: CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL,
49
+ restrict: (e: ICoreMouseEvent) => {
50
+ // no move
51
+ if (e.action === CoreMouseAction.MOVE) {
52
+ return false;
53
+ }
54
+ return true;
55
+ }
56
+ },
57
+ /**
58
+ * DRAG
59
+ * Events: mousedown / mouseup / wheel / mousedrag
60
+ * Modifiers: all
61
+ */
62
+ DRAG: {
63
+ events: CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL | CoreMouseEventType.DRAG,
64
+ restrict: (e: ICoreMouseEvent) => {
65
+ // no move without button
66
+ if (e.action === CoreMouseAction.MOVE && e.button === CoreMouseButton.NONE) {
67
+ return false;
68
+ }
69
+ return true;
70
+ }
71
+ },
72
+ /**
73
+ * ANY
74
+ * Events: all mouse related events
75
+ * Modifiers: all
76
+ */
77
+ ANY: {
78
+ events:
79
+ CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL
80
+ | CoreMouseEventType.DRAG | CoreMouseEventType.MOVE,
81
+ restrict: (e: ICoreMouseEvent) => true
82
+ }
83
+ };
84
+
85
+ const enum Modifiers {
86
+ SHIFT = 4,
87
+ ALT = 8,
88
+ CTRL = 16
89
+ }
90
+
91
+ // helper for default encoders to generate the event code.
92
+ function eventCode(e: ICoreMouseEvent, isSGR: boolean): number {
93
+ let code = (e.ctrl ? Modifiers.CTRL : 0) | (e.shift ? Modifiers.SHIFT : 0) | (e.alt ? Modifiers.ALT : 0);
94
+ if (e.button === CoreMouseButton.WHEEL) {
95
+ code |= 64;
96
+ code |= e.action;
97
+ } else {
98
+ code |= e.button & 3;
99
+ if (e.button & 4) {
100
+ code |= 64;
101
+ }
102
+ if (e.button & 8) {
103
+ code |= 128;
104
+ }
105
+ if (e.action === CoreMouseAction.MOVE) {
106
+ code |= CoreMouseAction.MOVE;
107
+ } else if (e.action === CoreMouseAction.UP && !isSGR) {
108
+ // special case - only SGR can report button on release
109
+ // all others have to go with NONE
110
+ code |= CoreMouseButton.NONE;
111
+ }
112
+ }
113
+ return code;
114
+ }
115
+
116
+ const S = String.fromCharCode;
117
+
118
+ /**
119
+ * Supported default encodings.
120
+ */
121
+ const DEFAULT_ENCODINGS: { [key: string]: CoreMouseEncoding } = {
122
+ /**
123
+ * DEFAULT - CSI M Pb Px Py
124
+ * Single byte encoding for coords and event code.
125
+ * Can encode values up to 223 (1-based).
126
+ */
127
+ DEFAULT: (e: ICoreMouseEvent) => {
128
+ const params = [eventCode(e, false) + 32, e.col + 32, e.row + 32];
129
+ // supress mouse report if we exceed addressible range
130
+ // Note this is handled differently by emulators
131
+ // - xterm: sends 0;0 coords instead
132
+ // - vte, konsole: no report
133
+ if (params[0] > 255 || params[1] > 255 || params[2] > 255) {
134
+ return '';
135
+ }
136
+ return `\x1b[M${S(params[0])}${S(params[1])}${S(params[2])}`;
137
+ },
138
+ /**
139
+ * SGR - CSI < Pb ; Px ; Py M|m
140
+ * No encoding limitation.
141
+ * Can report button on release and works with a well formed sequence.
142
+ */
143
+ SGR: (e: ICoreMouseEvent) => {
144
+ const final = (e.action === CoreMouseAction.UP && e.button !== CoreMouseButton.WHEEL) ? 'm' : 'M';
145
+ return `\x1b[<${eventCode(e, true)};${e.col};${e.row}${final}`;
146
+ },
147
+ SGR_PIXELS: (e: ICoreMouseEvent) => {
148
+ const final = (e.action === CoreMouseAction.UP && e.button !== CoreMouseButton.WHEEL) ? 'm' : 'M';
149
+ return `\x1b[<${eventCode(e, true)};${e.x};${e.y}${final}`;
150
+ }
151
+ };
152
+
153
+ /**
154
+ * CoreMouseService
155
+ *
156
+ * Provides mouse tracking reports with different protocols and encodings.
157
+ * - protocols: NONE (default), X10, VT200, DRAG, ANY
158
+ * - encodings: DEFAULT, SGR (UTF8, URXVT removed in #2507)
159
+ *
160
+ * Custom protocols/encodings can be added by `addProtocol` / `addEncoding`.
161
+ * To activate a protocol/encoding, set `activeProtocol` / `activeEncoding`.
162
+ * Switching a protocol will send a notification event `onProtocolChange`
163
+ * with a list of needed events to track.
164
+ *
165
+ * The service handles the mouse tracking state and decides whether to send
166
+ * a tracking report to the backend based on protocol and encoding limitations.
167
+ * To send a mouse event call `triggerMouseEvent`.
168
+ */
169
+ export class CoreMouseService extends Disposable implements ICoreMouseService {
170
+ private _protocols: { [name: string]: ICoreMouseProtocol } = {};
171
+ private _encodings: { [name: string]: CoreMouseEncoding } = {};
172
+ private _activeProtocol: string = '';
173
+ private _activeEncoding: string = '';
174
+ private _lastEvent: ICoreMouseEvent | null = null;
175
+
176
+ private readonly _onProtocolChange = this.register(new EventEmitter<CoreMouseEventType>());
177
+ public readonly onProtocolChange = this._onProtocolChange.event;
178
+
179
+ constructor(
180
+ @IBufferService private readonly _bufferService: IBufferService,
181
+ @ICoreService private readonly _coreService: ICoreService
182
+ ) {
183
+ super();
184
+ // register default protocols and encodings
185
+ for (const name of Object.keys(DEFAULT_PROTOCOLS)) this.addProtocol(name, DEFAULT_PROTOCOLS[name]);
186
+ for (const name of Object.keys(DEFAULT_ENCODINGS)) this.addEncoding(name, DEFAULT_ENCODINGS[name]);
187
+ // call reset to set defaults
188
+ this.reset();
189
+ }
190
+
191
+ public addProtocol(name: string, protocol: ICoreMouseProtocol): void {
192
+ this._protocols[name] = protocol;
193
+ }
194
+
195
+ public addEncoding(name: string, encoding: CoreMouseEncoding): void {
196
+ this._encodings[name] = encoding;
197
+ }
198
+
199
+ public get activeProtocol(): string {
200
+ return this._activeProtocol;
201
+ }
202
+
203
+ public get areMouseEventsActive(): boolean {
204
+ return this._protocols[this._activeProtocol].events !== 0;
205
+ }
206
+
207
+ public set activeProtocol(name: string) {
208
+ if (!this._protocols[name]) {
209
+ throw new Error(`unknown protocol "${name}"`);
210
+ }
211
+ this._activeProtocol = name;
212
+ this._onProtocolChange.fire(this._protocols[name].events);
213
+ }
214
+
215
+ public get activeEncoding(): string {
216
+ return this._activeEncoding;
217
+ }
218
+
219
+ public set activeEncoding(name: string) {
220
+ if (!this._encodings[name]) {
221
+ throw new Error(`unknown encoding "${name}"`);
222
+ }
223
+ this._activeEncoding = name;
224
+ }
225
+
226
+ public reset(): void {
227
+ this.activeProtocol = 'NONE';
228
+ this.activeEncoding = 'DEFAULT';
229
+ this._lastEvent = null;
230
+ }
231
+
232
+ /**
233
+ * Triggers a mouse event to be sent.
234
+ *
235
+ * Returns true if the event passed all protocol restrictions and a report
236
+ * was sent, otherwise false. The return value may be used to decide whether
237
+ * the default event action in the bowser component should be omitted.
238
+ *
239
+ * Note: The method will change values of the given event object
240
+ * to fullfill protocol and encoding restrictions.
241
+ */
242
+ public triggerMouseEvent(e: ICoreMouseEvent): boolean {
243
+ // range check for col/row
244
+ if (e.col < 0 || e.col >= this._bufferService.cols
245
+ || e.row < 0 || e.row >= this._bufferService.rows) {
246
+ return false;
247
+ }
248
+
249
+ // filter nonsense combinations of button + action
250
+ if (e.button === CoreMouseButton.WHEEL && e.action === CoreMouseAction.MOVE) {
251
+ return false;
252
+ }
253
+ if (e.button === CoreMouseButton.NONE && e.action !== CoreMouseAction.MOVE) {
254
+ return false;
255
+ }
256
+ if (e.button !== CoreMouseButton.WHEEL && (e.action === CoreMouseAction.LEFT || e.action === CoreMouseAction.RIGHT)) {
257
+ return false;
258
+ }
259
+
260
+ // report 1-based coords
261
+ e.col++;
262
+ e.row++;
263
+
264
+ // debounce move events at grid or pixel level
265
+ if (e.action === CoreMouseAction.MOVE
266
+ && this._lastEvent
267
+ && this._equalEvents(this._lastEvent, e, this._activeEncoding === 'SGR_PIXELS')
268
+ ) {
269
+ return false;
270
+ }
271
+
272
+ // apply protocol restrictions
273
+ if (!this._protocols[this._activeProtocol].restrict(e)) {
274
+ return false;
275
+ }
276
+
277
+ // encode report and send
278
+ const report = this._encodings[this._activeEncoding](e);
279
+ if (report) {
280
+ // always send DEFAULT as binary data
281
+ if (this._activeEncoding === 'DEFAULT') {
282
+ this._coreService.triggerBinaryEvent(report);
283
+ } else {
284
+ this._coreService.triggerDataEvent(report, true);
285
+ }
286
+ }
287
+
288
+ this._lastEvent = e;
289
+
290
+ return true;
291
+ }
292
+
293
+ public explainEvents(events: CoreMouseEventType): { [event: string]: boolean } {
294
+ return {
295
+ down: !!(events & CoreMouseEventType.DOWN),
296
+ up: !!(events & CoreMouseEventType.UP),
297
+ drag: !!(events & CoreMouseEventType.DRAG),
298
+ move: !!(events & CoreMouseEventType.MOVE),
299
+ wheel: !!(events & CoreMouseEventType.WHEEL)
300
+ };
301
+ }
302
+
303
+ private _equalEvents(e1: ICoreMouseEvent, e2: ICoreMouseEvent, pixels: boolean): boolean {
304
+ if (pixels) {
305
+ if (e1.x !== e2.x) return false;
306
+ if (e1.y !== e2.y) return false;
307
+ } else {
308
+ if (e1.col !== e2.col) return false;
309
+ if (e1.row !== e2.row) return false;
310
+ }
311
+ if (e1.button !== e2.button) return false;
312
+ if (e1.action !== e2.action) return false;
313
+ if (e1.ctrl !== e2.ctrl) return false;
314
+ if (e1.alt !== e2.alt) return false;
315
+ if (e1.shift !== e2.shift) return false;
316
+ return true;
317
+ }
318
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { clone } from 'common/Clone';
7
+ import { EventEmitter } from 'common/EventEmitter';
8
+ import { Disposable } from 'common/Lifecycle';
9
+ import { IDecPrivateModes, IModes } from 'common/Types';
10
+ import { IBufferService, ICoreService, ILogService, IOptionsService } from 'common/services/Services';
11
+
12
+ const DEFAULT_MODES: IModes = Object.freeze({
13
+ insertMode: false
14
+ });
15
+
16
+ const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({
17
+ applicationCursorKeys: false,
18
+ applicationKeypad: false,
19
+ bracketedPasteMode: false,
20
+ origin: false,
21
+ reverseWraparound: false,
22
+ sendFocus: false,
23
+ wraparound: true // defaults: xterm - true, vt100 - false
24
+ });
25
+
26
+ export class CoreService extends Disposable implements ICoreService {
27
+ public serviceBrand: any;
28
+
29
+ public isCursorInitialized: boolean = false;
30
+ public isCursorHidden: boolean = false;
31
+ public modes: IModes;
32
+ public decPrivateModes: IDecPrivateModes;
33
+
34
+ private readonly _onData = this.register(new EventEmitter<string>());
35
+ public readonly onData = this._onData.event;
36
+ private readonly _onUserInput = this.register(new EventEmitter<void>());
37
+ public readonly onUserInput = this._onUserInput.event;
38
+ private readonly _onBinary = this.register(new EventEmitter<string>());
39
+ public readonly onBinary = this._onBinary.event;
40
+ private readonly _onRequestScrollToBottom = this.register(new EventEmitter<void>());
41
+ public readonly onRequestScrollToBottom = this._onRequestScrollToBottom.event;
42
+
43
+ constructor(
44
+ @IBufferService private readonly _bufferService: IBufferService,
45
+ @ILogService private readonly _logService: ILogService,
46
+ @IOptionsService private readonly _optionsService: IOptionsService
47
+ ) {
48
+ super();
49
+ this.modes = clone(DEFAULT_MODES);
50
+ this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
51
+ }
52
+
53
+ public reset(): void {
54
+ this.modes = clone(DEFAULT_MODES);
55
+ this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
56
+ }
57
+
58
+ public triggerDataEvent(data: string, wasUserInput: boolean = false): void {
59
+ // Prevents all events to pty process if stdin is disabled
60
+ if (this._optionsService.rawOptions.disableStdin) {
61
+ return;
62
+ }
63
+
64
+ // Input is being sent to the terminal, the terminal should focus the prompt.
65
+ const buffer = this._bufferService.buffer;
66
+ if (wasUserInput && this._optionsService.rawOptions.scrollOnUserInput && buffer.ybase !== buffer.ydisp) {
67
+ this._onRequestScrollToBottom.fire();
68
+ }
69
+
70
+ // Fire onUserInput so listeners can react as well (eg. clear selection)
71
+ if (wasUserInput) {
72
+ this._onUserInput.fire();
73
+ }
74
+
75
+ // Fire onData API
76
+ this._logService.debug(`sending data "${data}"`, () => data.split('').map(e => e.charCodeAt(0)));
77
+ this._onData.fire(data);
78
+ }
79
+
80
+ public triggerBinaryEvent(data: string): void {
81
+ if (this._optionsService.rawOptions.disableStdin) {
82
+ return;
83
+ }
84
+ this._logService.debug(`sending binary "${data}"`, () => data.split('').map(e => e.charCodeAt(0)));
85
+ this._onBinary.fire(data);
86
+ }
87
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Copyright (c) 2022 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { css } from 'common/Color';
7
+ import { EventEmitter } from 'common/EventEmitter';
8
+ import { Disposable, toDisposable } from 'common/Lifecycle';
9
+ import { IDecorationService, IInternalDecoration } from 'common/services/Services';
10
+ import { SortedList } from 'common/SortedList';
11
+ import { IColor } from 'common/Types';
12
+ import { IDecoration, IDecorationOptions, IMarker } from '@xterm/xterm';
13
+
14
+ // Work variables to avoid garbage collection
15
+ let $xmin = 0;
16
+ let $xmax = 0;
17
+
18
+ export class DecorationService extends Disposable implements IDecorationService {
19
+ public serviceBrand: any;
20
+
21
+ /**
22
+ * A list of all decorations, sorted by the marker's line value. This relies on the fact that
23
+ * while marker line values do change, they should all change by the same amount so this should
24
+ * never become out of order.
25
+ */
26
+ private readonly _decorations: SortedList<IInternalDecoration> = new SortedList(e => e?.marker.line);
27
+
28
+ private readonly _onDecorationRegistered = this.register(new EventEmitter<IInternalDecoration>());
29
+ public readonly onDecorationRegistered = this._onDecorationRegistered.event;
30
+ private readonly _onDecorationRemoved = this.register(new EventEmitter<IInternalDecoration>());
31
+ public readonly onDecorationRemoved = this._onDecorationRemoved.event;
32
+
33
+ public get decorations(): IterableIterator<IInternalDecoration> { return this._decorations.values(); }
34
+
35
+ constructor() {
36
+ super();
37
+
38
+ this.register(toDisposable(() => this.reset()));
39
+ }
40
+
41
+ public registerDecoration(options: IDecorationOptions): IDecoration | undefined {
42
+ if (options.marker.isDisposed) {
43
+ return undefined;
44
+ }
45
+ const decoration = new Decoration(options);
46
+ if (decoration) {
47
+ const markerDispose = decoration.marker.onDispose(() => decoration.dispose());
48
+ decoration.onDispose(() => {
49
+ if (decoration) {
50
+ if (this._decorations.delete(decoration)) {
51
+ this._onDecorationRemoved.fire(decoration);
52
+ }
53
+ markerDispose.dispose();
54
+ }
55
+ });
56
+ this._decorations.insert(decoration);
57
+ this._onDecorationRegistered.fire(decoration);
58
+ }
59
+ return decoration;
60
+ }
61
+
62
+ public reset(): void {
63
+ for (const d of this._decorations.values()) {
64
+ d.dispose();
65
+ }
66
+ this._decorations.clear();
67
+ }
68
+
69
+ public *getDecorationsAtCell(x: number, line: number, layer?: 'bottom' | 'top'): IterableIterator<IInternalDecoration> {
70
+ let xmin = 0;
71
+ let xmax = 0;
72
+ for (const d of this._decorations.getKeyIterator(line)) {
73
+ xmin = d.options.x ?? 0;
74
+ xmax = xmin + (d.options.width ?? 1);
75
+ if (x >= xmin && x < xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) {
76
+ yield d;
77
+ }
78
+ }
79
+ }
80
+
81
+ public forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void {
82
+ this._decorations.forEachByKey(line, d => {
83
+ $xmin = d.options.x ?? 0;
84
+ $xmax = $xmin + (d.options.width ?? 1);
85
+ if (x >= $xmin && x < $xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) {
86
+ callback(d);
87
+ }
88
+ });
89
+ }
90
+ }
91
+
92
+ class Decoration extends Disposable implements IInternalDecoration {
93
+ public readonly marker: IMarker;
94
+ public element: HTMLElement | undefined;
95
+ public get isDisposed(): boolean { return this._isDisposed; }
96
+
97
+ public readonly onRenderEmitter = this.register(new EventEmitter<HTMLElement>());
98
+ public readonly onRender = this.onRenderEmitter.event;
99
+ private readonly _onDispose = this.register(new EventEmitter<void>());
100
+ public readonly onDispose = this._onDispose.event;
101
+
102
+ private _cachedBg: IColor | undefined | null = null;
103
+ public get backgroundColorRGB(): IColor | undefined {
104
+ if (this._cachedBg === null) {
105
+ if (this.options.backgroundColor) {
106
+ this._cachedBg = css.toColor(this.options.backgroundColor);
107
+ } else {
108
+ this._cachedBg = undefined;
109
+ }
110
+ }
111
+ return this._cachedBg;
112
+ }
113
+
114
+ private _cachedFg: IColor | undefined | null = null;
115
+ public get foregroundColorRGB(): IColor | undefined {
116
+ if (this._cachedFg === null) {
117
+ if (this.options.foregroundColor) {
118
+ this._cachedFg = css.toColor(this.options.foregroundColor);
119
+ } else {
120
+ this._cachedFg = undefined;
121
+ }
122
+ }
123
+ return this._cachedFg;
124
+ }
125
+
126
+ constructor(
127
+ public readonly options: IDecorationOptions
128
+ ) {
129
+ super();
130
+ this.marker = options.marker;
131
+ if (this.options.overviewRulerOptions && !this.options.overviewRulerOptions.position) {
132
+ this.options.overviewRulerOptions.position = 'full';
133
+ }
134
+ }
135
+
136
+ public override dispose(): void {
137
+ this._onDispose.fire();
138
+ super.dispose();
139
+ }
140
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ *
5
+ * This was heavily inspired from microsoft/vscode's dependency injection system (MIT).
6
+ */
7
+ /*---------------------------------------------------------------------------------------------
8
+ * Copyright (c) Microsoft Corporation. All rights reserved.
9
+ * Licensed under the MIT License. See License.txt in the project root for license information.
10
+ *--------------------------------------------------------------------------------------------*/
11
+
12
+ import { IInstantiationService, IServiceIdentifier } from 'common/services/Services';
13
+ import { getServiceDependencies } from 'common/services/ServiceRegistry';
14
+
15
+ export class ServiceCollection {
16
+
17
+ private _entries = new Map<IServiceIdentifier<any>, any>();
18
+
19
+ constructor(...entries: [IServiceIdentifier<any>, any][]) {
20
+ for (const [id, service] of entries) {
21
+ this.set(id, service);
22
+ }
23
+ }
24
+
25
+ public set<T>(id: IServiceIdentifier<T>, instance: T): T {
26
+ const result = this._entries.get(id);
27
+ this._entries.set(id, instance);
28
+ return result;
29
+ }
30
+
31
+ public forEach(callback: (id: IServiceIdentifier<any>, instance: any) => any): void {
32
+ for (const [key, value] of this._entries.entries()) {
33
+ callback(key, value);
34
+ }
35
+ }
36
+
37
+ public has(id: IServiceIdentifier<any>): boolean {
38
+ return this._entries.has(id);
39
+ }
40
+
41
+ public get<T>(id: IServiceIdentifier<T>): T | undefined {
42
+ return this._entries.get(id);
43
+ }
44
+ }
45
+
46
+ export class InstantiationService implements IInstantiationService {
47
+ public serviceBrand: undefined;
48
+
49
+ private readonly _services: ServiceCollection = new ServiceCollection();
50
+
51
+ constructor() {
52
+ this._services.set(IInstantiationService, this);
53
+ }
54
+
55
+ public setService<T>(id: IServiceIdentifier<T>, instance: T): void {
56
+ this._services.set(id, instance);
57
+ }
58
+
59
+ public getService<T>(id: IServiceIdentifier<T>): T | undefined {
60
+ return this._services.get(id);
61
+ }
62
+
63
+ public createInstance<T>(ctor: any, ...args: any[]): T {
64
+ const serviceDependencies = getServiceDependencies(ctor).sort((a, b) => a.index - b.index);
65
+
66
+ const serviceArgs: any[] = [];
67
+ for (const dependency of serviceDependencies) {
68
+ const service = this._services.get(dependency.id);
69
+ if (!service) {
70
+ throw new Error(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`);
71
+ }
72
+ serviceArgs.push(service);
73
+ }
74
+
75
+ const firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;
76
+
77
+ // check for argument mismatches, adjust static args if needed
78
+ if (args.length !== firstServiceArgPos) {
79
+ throw new Error(`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`);
80
+ }
81
+
82
+ // now create the instance
83
+ return new ctor(...[...args, ...serviceArgs]);
84
+ }
85
+ }