@xterm/xterm 5.4.0-beta.20 → 5.4.0-beta.22
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.
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/package.json +1 -1
- package/src/browser/{Linkifier2.ts → Linkifier.ts} +34 -62
- package/src/browser/OscLinkProvider.ts +2 -1
- package/src/browser/Terminal.ts +24 -18
- package/src/browser/Types.d.ts +1 -9
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +3 -3
- package/src/browser/renderer/shared/TextureAtlas.ts +4 -5
- package/src/browser/services/LinkProviderService.ts +28 -0
- package/src/browser/services/Services.ts +12 -1
- package/src/common/Color.ts +11 -12
- package/src/common/CoreTerminal.ts +1 -0
- package/src/common/Types.d.ts +2 -2
package/package.json
CHANGED
|
@@ -4,18 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { addDisposableDomListener } from 'browser/Lifecycle';
|
|
7
|
-
import { IBufferCellPosition, ILink, ILinkDecorations,
|
|
7
|
+
import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types';
|
|
8
8
|
import { EventEmitter } from 'common/EventEmitter';
|
|
9
9
|
import { Disposable, disposeArray, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
|
|
10
10
|
import { IDisposable } from 'common/Types';
|
|
11
11
|
import { IBufferService } from 'common/services/Services';
|
|
12
|
-
import { IMouseService, IRenderService } from './services/Services';
|
|
12
|
+
import { ILinkProviderService, IMouseService, IRenderService } from './services/Services';
|
|
13
13
|
|
|
14
|
-
export class
|
|
15
|
-
private _element: HTMLElement | undefined;
|
|
16
|
-
private _mouseService: IMouseService | undefined;
|
|
17
|
-
private _renderService: IRenderService | undefined;
|
|
18
|
-
private _linkProviders: ILinkProvider[] = [];
|
|
14
|
+
export class Linkifier extends Disposable implements ILinkifier2 {
|
|
19
15
|
public get currentLink(): ILinkWithState | undefined { return this._currentLink; }
|
|
20
16
|
protected _currentLink: ILinkWithState | undefined;
|
|
21
17
|
private _mouseDownLink: ILinkWithState | undefined;
|
|
@@ -33,14 +29,17 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
33
29
|
public readonly onHideLinkUnderline = this._onHideLinkUnderline.event;
|
|
34
30
|
|
|
35
31
|
constructor(
|
|
36
|
-
|
|
32
|
+
private readonly _element: HTMLElement,
|
|
33
|
+
@IMouseService private readonly _mouseService: IMouseService,
|
|
34
|
+
@IRenderService private readonly _renderService: IRenderService,
|
|
35
|
+
@IBufferService private readonly _bufferService: IBufferService,
|
|
36
|
+
@ILinkProviderService private readonly _linkProviderService: ILinkProviderService
|
|
37
37
|
) {
|
|
38
38
|
super();
|
|
39
39
|
this.register(getDisposeArrayDisposable(this._linkCacheDisposables));
|
|
40
40
|
this.register(toDisposable(() => {
|
|
41
41
|
this._lastMouseEvent = undefined;
|
|
42
42
|
// Clear out link providers as they could easily cause an embedder memory leak
|
|
43
|
-
this._linkProviders.length = 0;
|
|
44
43
|
this._activeProviderReplies?.clear();
|
|
45
44
|
}));
|
|
46
45
|
// Listen to resize to catch the case where it's resized and the cursor is out of the viewport.
|
|
@@ -48,27 +47,6 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
48
47
|
this._clearCurrentLink();
|
|
49
48
|
this._wasResized = true;
|
|
50
49
|
}));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
54
|
-
this._linkProviders.push(linkProvider);
|
|
55
|
-
return {
|
|
56
|
-
dispose: () => {
|
|
57
|
-
// Remove the link provider from the list
|
|
58
|
-
const providerIndex = this._linkProviders.indexOf(linkProvider);
|
|
59
|
-
|
|
60
|
-
if (providerIndex !== -1) {
|
|
61
|
-
this._linkProviders.splice(providerIndex, 1);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
public attachToDom(element: HTMLElement, mouseService: IMouseService, renderService: IRenderService): void {
|
|
68
|
-
this._element = element;
|
|
69
|
-
this._mouseService = mouseService;
|
|
70
|
-
this._renderService = renderService;
|
|
71
|
-
|
|
72
50
|
this.register(addDisposableDomListener(this._element, 'mouseleave', () => {
|
|
73
51
|
this._isMouseOut = true;
|
|
74
52
|
this._clearCurrentLink();
|
|
@@ -81,10 +59,6 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
81
59
|
private _handleMouseMove(event: MouseEvent): void {
|
|
82
60
|
this._lastMouseEvent = event;
|
|
83
61
|
|
|
84
|
-
if (!this._element || !this._mouseService) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
62
|
const position = this._positionFromMouseEvent(event, this._element, this._mouseService);
|
|
89
63
|
if (!position) {
|
|
90
64
|
return;
|
|
@@ -145,7 +119,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
145
119
|
let linkProvided = false;
|
|
146
120
|
|
|
147
121
|
// There is no link cached, so ask for one
|
|
148
|
-
for (const [i, linkProvider] of this.
|
|
122
|
+
for (const [i, linkProvider] of this._linkProviderService.linkProviders.entries()) {
|
|
149
123
|
if (useLineCache) {
|
|
150
124
|
const existingReply = this._activeProviderReplies?.get(i);
|
|
151
125
|
// If there isn't a reply, the provider hasn't responded yet.
|
|
@@ -167,7 +141,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
167
141
|
|
|
168
142
|
// If all providers have responded, remove lower priority links that intersect ranges of
|
|
169
143
|
// higher priority links
|
|
170
|
-
if (this._activeProviderReplies?.size === this.
|
|
144
|
+
if (this._activeProviderReplies?.size === this._linkProviderService.linkProviders.length) {
|
|
171
145
|
this._removeIntersectingLinks(position.y, this._activeProviderReplies);
|
|
172
146
|
}
|
|
173
147
|
});
|
|
@@ -223,7 +197,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
223
197
|
}
|
|
224
198
|
|
|
225
199
|
// Check if all the providers have responded
|
|
226
|
-
if (this._activeProviderReplies.size === this.
|
|
200
|
+
if (this._activeProviderReplies.size === this._linkProviderService.linkProviders.length && !linkProvided) {
|
|
227
201
|
// Respect the order of the link providers
|
|
228
202
|
for (let j = 0; j < this._activeProviderReplies.size; j++) {
|
|
229
203
|
const currentLink = this._activeProviderReplies.get(j)?.find(link => this._linkAtPosition(link.link, position));
|
|
@@ -243,7 +217,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
243
217
|
}
|
|
244
218
|
|
|
245
219
|
private _handleMouseUp(event: MouseEvent): void {
|
|
246
|
-
if (!this.
|
|
220
|
+
if (!this._currentLink) {
|
|
247
221
|
return;
|
|
248
222
|
}
|
|
249
223
|
|
|
@@ -258,7 +232,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
258
232
|
}
|
|
259
233
|
|
|
260
234
|
private _clearCurrentLink(startRow?: number, endRow?: number): void {
|
|
261
|
-
if (!this.
|
|
235
|
+
if (!this._currentLink || !this._lastMouseEvent) {
|
|
262
236
|
return;
|
|
263
237
|
}
|
|
264
238
|
|
|
@@ -271,7 +245,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
271
245
|
}
|
|
272
246
|
|
|
273
247
|
private _handleNewLink(linkWithState: ILinkWithState): void {
|
|
274
|
-
if (!this.
|
|
248
|
+
if (!this._lastMouseEvent) {
|
|
275
249
|
return;
|
|
276
250
|
}
|
|
277
251
|
|
|
@@ -302,7 +276,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
302
276
|
if (this._currentLink?.state && this._currentLink.state.decorations.pointerCursor !== v) {
|
|
303
277
|
this._currentLink.state.decorations.pointerCursor = v;
|
|
304
278
|
if (this._currentLink.state.isHovered) {
|
|
305
|
-
this._element
|
|
279
|
+
this._element.classList.toggle('xterm-cursor-pointer', v);
|
|
306
280
|
}
|
|
307
281
|
}
|
|
308
282
|
}
|
|
@@ -322,29 +296,27 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
|
|
|
322
296
|
|
|
323
297
|
// Listen to viewport changes to re-render the link under the cursor (only when the line the
|
|
324
298
|
// link is on changes)
|
|
325
|
-
|
|
326
|
-
this
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
this._askForLink(position, false);
|
|
343
|
-
}
|
|
299
|
+
this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange(e => {
|
|
300
|
+
// Sanity check, this shouldn't happen in practice as this listener would be disposed
|
|
301
|
+
if (!this._currentLink) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
// When start is 0 a scroll most likely occurred, make sure links above the fold also get
|
|
305
|
+
// cleared.
|
|
306
|
+
const start = e.start === 0 ? 0 : e.start + 1 + this._bufferService.buffer.ydisp;
|
|
307
|
+
const end = this._bufferService.buffer.ydisp + 1 + e.end;
|
|
308
|
+
// Only clear the link if the viewport change happened on this line
|
|
309
|
+
if (this._currentLink.link.range.start.y >= start && this._currentLink.link.range.end.y <= end) {
|
|
310
|
+
this._clearCurrentLink(start, end);
|
|
311
|
+
if (this._lastMouseEvent) {
|
|
312
|
+
// re-eval previously active link after changes
|
|
313
|
+
const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element, this._mouseService!);
|
|
314
|
+
if (position) {
|
|
315
|
+
this._askForLink(position, false);
|
|
344
316
|
}
|
|
345
317
|
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
318
|
+
}
|
|
319
|
+
}));
|
|
348
320
|
}
|
|
349
321
|
}
|
|
350
322
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IBufferRange, ILink
|
|
6
|
+
import { IBufferRange, ILink } from 'browser/Types';
|
|
7
|
+
import { ILinkProvider } from 'browser/services/Services';
|
|
7
8
|
import { CellData } from 'common/buffer/CellData';
|
|
8
9
|
import { IBufferService, IOptionsService, IOscLinkService } from 'common/services/Services';
|
|
9
10
|
|
package/src/browser/Terminal.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard';
|
|
25
25
|
import { addDisposableDomListener } from 'browser/Lifecycle';
|
|
26
|
-
import {
|
|
26
|
+
import { Linkifier } from './Linkifier';
|
|
27
27
|
import * as Strings from 'browser/LocalizableStrings';
|
|
28
28
|
import { OscLinkProvider } from 'browser/OscLinkProvider';
|
|
29
29
|
import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal, IViewport } from 'browser/Types';
|
|
@@ -39,9 +39,9 @@ import { CoreBrowserService } from 'browser/services/CoreBrowserService';
|
|
|
39
39
|
import { MouseService } from 'browser/services/MouseService';
|
|
40
40
|
import { RenderService } from 'browser/services/RenderService';
|
|
41
41
|
import { SelectionService } from 'browser/services/SelectionService';
|
|
42
|
-
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
|
|
42
|
+
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, ILinkProviderService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
|
|
43
43
|
import { ThemeService } from 'browser/services/ThemeService';
|
|
44
|
-
import {
|
|
44
|
+
import { channels, color } from 'common/Color';
|
|
45
45
|
import { CoreTerminal } from 'common/CoreTerminal';
|
|
46
46
|
import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
|
|
47
47
|
import { MutableDisposable, toDisposable } from 'common/Lifecycle';
|
|
@@ -57,6 +57,7 @@ import { IDecorationService } from 'common/services/Services';
|
|
|
57
57
|
import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
|
|
58
58
|
import { WindowsOptionsReportType } from '../common/InputHandler';
|
|
59
59
|
import { AccessibilityManager } from './AccessibilityManager';
|
|
60
|
+
import { LinkProviderService } from 'browser/services/LinkProviderService';
|
|
60
61
|
|
|
61
62
|
export class Terminal extends CoreTerminal implements ITerminal {
|
|
62
63
|
public textarea: HTMLTextAreaElement | undefined;
|
|
@@ -69,6 +70,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
69
70
|
private _helperContainer: HTMLElement | undefined;
|
|
70
71
|
private _compositionView: HTMLElement | undefined;
|
|
71
72
|
|
|
73
|
+
public linkifier: ILinkifier2 | undefined;
|
|
72
74
|
private _overviewRulerRenderer: OverviewRulerRenderer | undefined;
|
|
73
75
|
|
|
74
76
|
public browser: IBrowser = Browser as any;
|
|
@@ -76,8 +78,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
76
78
|
private _customKeyEventHandler: CustomKeyEventHandler | undefined;
|
|
77
79
|
private _customWheelEventHandler: CustomWheelEventHandler | undefined;
|
|
78
80
|
|
|
79
|
-
//
|
|
81
|
+
// Browser services
|
|
80
82
|
private _decorationService: DecorationService;
|
|
83
|
+
private _linkProviderService: ILinkProviderService;
|
|
84
|
+
|
|
85
|
+
// Optional browser services
|
|
81
86
|
private _charSizeService: ICharSizeService | undefined;
|
|
82
87
|
private _coreBrowserService: ICoreBrowserService | undefined;
|
|
83
88
|
private _mouseService: IMouseService | undefined;
|
|
@@ -113,7 +118,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
113
118
|
*/
|
|
114
119
|
private _unprocessedDeadKey: boolean = false;
|
|
115
120
|
|
|
116
|
-
public linkifier2: ILinkifier2;
|
|
117
121
|
public viewport: IViewport | undefined;
|
|
118
122
|
private _compositionHelper: ICompositionHelper | undefined;
|
|
119
123
|
private _accessibilityManager: MutableDisposable<AccessibilityManager> = this.register(new MutableDisposable());
|
|
@@ -149,10 +153,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
149
153
|
|
|
150
154
|
this._setup();
|
|
151
155
|
|
|
152
|
-
this.linkifier2 = this.register(this._instantiationService.createInstance(Linkifier2));
|
|
153
|
-
this.linkifier2.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
|
|
154
156
|
this._decorationService = this._instantiationService.createInstance(DecorationService);
|
|
155
157
|
this._instantiationService.setService(IDecorationService, this._decorationService);
|
|
158
|
+
this._linkProviderService = this._instantiationService.createInstance(LinkProviderService);
|
|
159
|
+
this._instantiationService.setService(ILinkProviderService, this._linkProviderService);
|
|
160
|
+
this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
|
|
156
161
|
|
|
157
162
|
// Setup InputHandler listeners
|
|
158
163
|
this.register(this._inputHandler.onRequestBell(() => this._onBell.fire()));
|
|
@@ -206,17 +211,17 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
206
211
|
}
|
|
207
212
|
switch (req.type) {
|
|
208
213
|
case ColorRequestType.REPORT:
|
|
209
|
-
const
|
|
214
|
+
const colorRgb = color.toColorRGB(acc === 'ansi'
|
|
210
215
|
? this._themeService.colors.ansi[req.index]
|
|
211
216
|
: this._themeService.colors[acc]);
|
|
212
|
-
this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(
|
|
217
|
+
this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1_ESCAPED.ST}`);
|
|
213
218
|
break;
|
|
214
219
|
case ColorRequestType.SET:
|
|
215
220
|
if (acc === 'ansi') {
|
|
216
|
-
this._themeService.modifyColors(colors => colors.ansi[req.index] =
|
|
221
|
+
this._themeService.modifyColors(colors => colors.ansi[req.index] = channels.toColor(...req.color));
|
|
217
222
|
} else {
|
|
218
223
|
const narrowedAcc = acc;
|
|
219
|
-
this._themeService.modifyColors(colors => colors[narrowedAcc] =
|
|
224
|
+
this._themeService.modifyColors(colors => colors[narrowedAcc] = channels.toColor(...req.color));
|
|
220
225
|
}
|
|
221
226
|
break;
|
|
222
227
|
case ColorRequestType.RESTORE:
|
|
@@ -482,6 +487,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
482
487
|
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
|
|
483
488
|
this._helperContainer.appendChild(this._compositionView);
|
|
484
489
|
|
|
490
|
+
this._mouseService = this._instantiationService.createInstance(MouseService);
|
|
491
|
+
this._instantiationService.setService(IMouseService, this._mouseService);
|
|
492
|
+
|
|
493
|
+
this.linkifier = this.register(this._instantiationService.createInstance(Linkifier, this.screenElement));
|
|
494
|
+
|
|
485
495
|
// Performance: Add viewport and helper elements from the fragment
|
|
486
496
|
this.element.appendChild(fragment);
|
|
487
497
|
|
|
@@ -493,9 +503,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
493
503
|
this._renderService.setRenderer(this._createRenderer());
|
|
494
504
|
}
|
|
495
505
|
|
|
496
|
-
this._mouseService = this._instantiationService.createInstance(MouseService);
|
|
497
|
-
this._instantiationService.setService(IMouseService, this._mouseService);
|
|
498
|
-
|
|
499
506
|
this.viewport = this._instantiationService.createInstance(Viewport, this._viewportElement, this._viewportScrollArea);
|
|
500
507
|
this.viewport.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent, ScrollSource.VIEWPORT)),
|
|
501
508
|
this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
|
|
@@ -513,7 +520,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
513
520
|
this._selectionService = this.register(this._instantiationService.createInstance(SelectionService,
|
|
514
521
|
this.element,
|
|
515
522
|
this.screenElement,
|
|
516
|
-
this.
|
|
523
|
+
this.linkifier
|
|
517
524
|
));
|
|
518
525
|
this._instantiationService.setService(ISelectionService, this._selectionService);
|
|
519
526
|
this.register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
|
|
@@ -533,7 +540,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
533
540
|
}));
|
|
534
541
|
this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh()));
|
|
535
542
|
|
|
536
|
-
this.linkifier2.attachToDom(this.screenElement, this._mouseService, this._renderService);
|
|
537
543
|
this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
|
|
538
544
|
this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
|
|
539
545
|
|
|
@@ -575,7 +581,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
575
581
|
}
|
|
576
582
|
|
|
577
583
|
private _createRenderer(): IRenderer {
|
|
578
|
-
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.
|
|
584
|
+
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
|
|
579
585
|
}
|
|
580
586
|
|
|
581
587
|
/**
|
|
@@ -894,7 +900,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|
|
894
900
|
}
|
|
895
901
|
|
|
896
902
|
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
897
|
-
return this.
|
|
903
|
+
return this._linkProviderService.registerLinkProvider(linkProvider);
|
|
898
904
|
}
|
|
899
905
|
|
|
900
906
|
public registerCharacterJoiner(handler: CharacterJoinerHandler): number {
|
package/src/browser/Types.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ import { IEvent } from 'common/EventEmitter';
|
|
|
7
7
|
import { CharData, IColor, ICoreTerminal, ITerminalOptions } from 'common/Types';
|
|
8
8
|
import { IBuffer } from 'common/buffer/Types';
|
|
9
9
|
import { IDisposable, Terminal as ITerminalApi } from '@xterm/xterm';
|
|
10
|
-
import { IMouseService, IRenderService } from './services/Services';
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* A portion of the public API that are implemented identially internally and simply passed through.
|
|
@@ -18,9 +17,9 @@ export interface ITerminal extends InternalPassthroughApis, ICoreTerminal {
|
|
|
18
17
|
screenElement: HTMLElement | undefined;
|
|
19
18
|
browser: IBrowser;
|
|
20
19
|
buffer: IBuffer;
|
|
20
|
+
linkifier: ILinkifier2 | undefined;
|
|
21
21
|
viewport: IViewport | undefined;
|
|
22
22
|
options: Required<ITerminalOptions>;
|
|
23
|
-
linkifier2: ILinkifier2;
|
|
24
23
|
|
|
25
24
|
onBlur: IEvent<void>;
|
|
26
25
|
onFocus: IEvent<void>;
|
|
@@ -128,13 +127,6 @@ export interface ILinkifier2 extends IDisposable {
|
|
|
128
127
|
onShowLinkUnderline: IEvent<ILinkifierEvent>;
|
|
129
128
|
onHideLinkUnderline: IEvent<ILinkifierEvent>;
|
|
130
129
|
readonly currentLink: ILinkWithState | undefined;
|
|
131
|
-
|
|
132
|
-
attachToDom(element: HTMLElement, mouseService: IMouseService, renderService: IRenderService): void;
|
|
133
|
-
registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
interface ILinkProvider {
|
|
137
|
-
provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void;
|
|
138
130
|
}
|
|
139
131
|
|
|
140
132
|
interface ILink {
|
|
@@ -8,7 +8,7 @@ import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
|
|
|
8
8
|
import { WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
|
|
9
9
|
import { CellData } from 'common/buffer/CellData';
|
|
10
10
|
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
|
|
11
|
-
import {
|
|
11
|
+
import { channels, color } from 'common/Color';
|
|
12
12
|
import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
|
13
13
|
import { JoinedCellData } from 'browser/services/CharacterJoinerService';
|
|
14
14
|
import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
|
|
@@ -376,7 +376,7 @@ export class DomRendererRowFactory {
|
|
|
376
376
|
classes.push(`xterm-bg-${bg}`);
|
|
377
377
|
break;
|
|
378
378
|
case Attributes.CM_RGB:
|
|
379
|
-
resolvedBg =
|
|
379
|
+
resolvedBg = channels.toColor(bg >> 16, bg >> 8 & 0xFF, bg & 0xFF);
|
|
380
380
|
this._addStyle(charElement, `background-color:#${padStart((bg >>> 0).toString(16), '0', 6)}`);
|
|
381
381
|
break;
|
|
382
382
|
case Attributes.CM_DEFAULT:
|
|
@@ -408,7 +408,7 @@ export class DomRendererRowFactory {
|
|
|
408
408
|
}
|
|
409
409
|
break;
|
|
410
410
|
case Attributes.CM_RGB:
|
|
411
|
-
const color =
|
|
411
|
+
const color = channels.toColor(
|
|
412
412
|
(fg >> 16) & 0xFF,
|
|
413
413
|
(fg >> 8) & 0xFF,
|
|
414
414
|
(fg ) & 0xFF
|
|
@@ -8,7 +8,7 @@ import { DIM_OPACITY, TEXT_BASELINE } from 'browser/renderer/shared/Constants';
|
|
|
8
8
|
import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs';
|
|
9
9
|
import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
|
10
10
|
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from 'browser/renderer/shared/Types';
|
|
11
|
-
import { NULL_COLOR, color, rgba } from 'common/Color';
|
|
11
|
+
import { NULL_COLOR, channels, color, rgba } from 'common/Color';
|
|
12
12
|
import { EventEmitter } from 'common/EventEmitter';
|
|
13
13
|
import { FourKeyMap } from 'common/MultiKeyMap';
|
|
14
14
|
import { IdleTaskQueue } from 'common/TaskQueue';
|
|
@@ -291,8 +291,7 @@ export class TextureAtlas implements ITextureAtlas {
|
|
|
291
291
|
break;
|
|
292
292
|
case Attributes.CM_RGB:
|
|
293
293
|
const arr = AttributeData.toColorRGB(bgColor);
|
|
294
|
-
|
|
295
|
-
result = rgba.toColor(arr[0], arr[1], arr[2]);
|
|
294
|
+
result = channels.toColor(arr[0], arr[1], arr[2]);
|
|
296
295
|
break;
|
|
297
296
|
case Attributes.CM_DEFAULT:
|
|
298
297
|
default:
|
|
@@ -324,7 +323,7 @@ export class TextureAtlas implements ITextureAtlas {
|
|
|
324
323
|
break;
|
|
325
324
|
case Attributes.CM_RGB:
|
|
326
325
|
const arr = AttributeData.toColorRGB(fgColor);
|
|
327
|
-
result =
|
|
326
|
+
result = channels.toColor(arr[0], arr[1], arr[2]);
|
|
328
327
|
break;
|
|
329
328
|
case Attributes.CM_DEFAULT:
|
|
330
329
|
default:
|
|
@@ -406,7 +405,7 @@ export class TextureAtlas implements ITextureAtlas {
|
|
|
406
405
|
return undefined;
|
|
407
406
|
}
|
|
408
407
|
|
|
409
|
-
const color =
|
|
408
|
+
const color = channels.toColor(
|
|
410
409
|
(result >> 24) & 0xFF,
|
|
411
410
|
(result >> 16) & 0xFF,
|
|
412
411
|
(result >> 8) & 0xFF
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ILinkProvider, ILinkProviderService } from 'browser/services/Services';
|
|
2
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
3
|
+
import { IDisposable } from 'common/Types';
|
|
4
|
+
|
|
5
|
+
export class LinkProviderService extends Disposable implements ILinkProviderService {
|
|
6
|
+
declare public serviceBrand: undefined;
|
|
7
|
+
|
|
8
|
+
public readonly linkProviders: ILinkProvider[] = [];
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.register(toDisposable(() => this.linkProviders.length = 0));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
|
|
16
|
+
this.linkProviders.push(linkProvider);
|
|
17
|
+
return {
|
|
18
|
+
dispose: () => {
|
|
19
|
+
// Remove the link provider from the list
|
|
20
|
+
const providerIndex = this.linkProviders.indexOf(linkProvider);
|
|
21
|
+
|
|
22
|
+
if (providerIndex !== -1) {
|
|
23
|
+
this.linkProviders.splice(providerIndex, 1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { IEvent } from 'common/EventEmitter';
|
|
7
7
|
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
|
8
|
-
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
|
8
|
+
import { IColorSet, ILink, ReadonlyColorSet } from 'browser/Types';
|
|
9
9
|
import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
|
|
10
10
|
import { createDecorator } from 'common/services/ServiceRegistry';
|
|
11
11
|
import { AllColorIndex, IDisposable } from 'common/Types';
|
|
@@ -145,3 +145,14 @@ export interface IThemeService {
|
|
|
145
145
|
*/
|
|
146
146
|
modifyColors(callback: (colors: IColorSet) => void): void;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
export const ILinkProviderService = createDecorator<ILinkProviderService>('LinkProviderService');
|
|
151
|
+
export interface ILinkProviderService extends IDisposable {
|
|
152
|
+
serviceBrand: undefined;
|
|
153
|
+
readonly linkProviders: ReadonlyArray<ILinkProvider>;
|
|
154
|
+
registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
|
|
155
|
+
}
|
|
156
|
+
export interface ILinkProvider {
|
|
157
|
+
provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void;
|
|
158
|
+
}
|
package/src/common/Color.ts
CHANGED
|
@@ -33,6 +33,13 @@ export namespace channels {
|
|
|
33
33
|
// >>> 0 forces an unsigned int
|
|
34
34
|
return (r << 24 | g << 16 | b << 8 | a) >>> 0;
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
export function toColor(r: number, g: number, b: number, a?: number): IColor {
|
|
38
|
+
return {
|
|
39
|
+
css: channels.toCss(r, g, b, a),
|
|
40
|
+
rgba: channels.toRgba(r, g, b, a)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
/**
|
|
@@ -70,7 +77,7 @@ export namespace color {
|
|
|
70
77
|
if (!result) {
|
|
71
78
|
return undefined;
|
|
72
79
|
}
|
|
73
|
-
return
|
|
80
|
+
return channels.toColor(
|
|
74
81
|
(result >> 24 & 0xFF),
|
|
75
82
|
(result >> 16 & 0xFF),
|
|
76
83
|
(result >> 8 & 0xFF)
|
|
@@ -142,14 +149,14 @@ export namespace css {
|
|
|
142
149
|
$r = parseInt(css.slice(1, 2).repeat(2), 16);
|
|
143
150
|
$g = parseInt(css.slice(2, 3).repeat(2), 16);
|
|
144
151
|
$b = parseInt(css.slice(3, 4).repeat(2), 16);
|
|
145
|
-
return
|
|
152
|
+
return channels.toColor($r, $g, $b);
|
|
146
153
|
}
|
|
147
154
|
case 5: { // #rgba
|
|
148
155
|
$r = parseInt(css.slice(1, 2).repeat(2), 16);
|
|
149
156
|
$g = parseInt(css.slice(2, 3).repeat(2), 16);
|
|
150
157
|
$b = parseInt(css.slice(3, 4).repeat(2), 16);
|
|
151
158
|
$a = parseInt(css.slice(4, 5).repeat(2), 16);
|
|
152
|
-
return
|
|
159
|
+
return channels.toColor($r, $g, $b, $a);
|
|
153
160
|
}
|
|
154
161
|
case 7: // #rrggbb
|
|
155
162
|
return {
|
|
@@ -171,7 +178,7 @@ export namespace css {
|
|
|
171
178
|
$g = parseInt(rgbaMatch[2]);
|
|
172
179
|
$b = parseInt(rgbaMatch[3]);
|
|
173
180
|
$a = Math.round((rgbaMatch[5] === undefined ? 1 : parseFloat(rgbaMatch[5])) * 0xFF);
|
|
174
|
-
return
|
|
181
|
+
return channels.toColor($r, $g, $b, $a);
|
|
175
182
|
}
|
|
176
183
|
|
|
177
184
|
// Validate the context is available for canvas-based color parsing
|
|
@@ -342,17 +349,9 @@ export namespace rgba {
|
|
|
342
349
|
return (fgR << 24 | fgG << 16 | fgB << 8 | 0xFF) >>> 0;
|
|
343
350
|
}
|
|
344
351
|
|
|
345
|
-
// FIXME: Move this to channels NS?
|
|
346
352
|
export function toChannels(value: number): [number, number, number, number] {
|
|
347
353
|
return [(value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF];
|
|
348
354
|
}
|
|
349
|
-
|
|
350
|
-
export function toColor(r: number, g: number, b: number, a?: number): IColor {
|
|
351
|
-
return {
|
|
352
|
-
css: channels.toCss(r, g, b, a),
|
|
353
|
-
rgba: channels.toRgba(r, g, b, a)
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
355
|
}
|
|
357
356
|
|
|
358
357
|
export function toPaddedHex(c: number): string {
|
|
@@ -120,6 +120,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
|
|
120
120
|
this._oscLinkService = this._instantiationService.createInstance(OscLinkService);
|
|
121
121
|
this._instantiationService.setService(IOscLinkService, this._oscLinkService);
|
|
122
122
|
|
|
123
|
+
|
|
123
124
|
// Register input handler and handle/forward events
|
|
124
125
|
this._inputHandler = this.register(new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService));
|
|
125
126
|
this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed));
|
package/src/common/Types.d.ts
CHANGED
|
@@ -110,8 +110,8 @@ export interface ICharset {
|
|
|
110
110
|
export type CharData = [number, string, number, number];
|
|
111
111
|
|
|
112
112
|
export interface IColor {
|
|
113
|
-
css: string;
|
|
114
|
-
rgba: number; // 32-bit int with rgba in each byte
|
|
113
|
+
readonly css: string;
|
|
114
|
+
readonly rgba: number; // 32-bit int with rgba in each byte
|
|
115
115
|
}
|
|
116
116
|
export type IColorRGB = [number, number, number];
|
|
117
117
|
|