@xterm/xterm 5.4.0-beta.9 → 5.4.0

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.
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { CharData, IAttributeData, IBufferLine, ICellData, IExtendedAttrs } from 'common/Types';
7
- import { AttributeData, ExtendedAttrs } from 'common/buffer/AttributeData';
7
+ import { AttributeData } from 'common/buffer/AttributeData';
8
8
  import { CellData } from 'common/buffer/CellData';
9
9
  import { Attributes, BgFlags, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, Content, NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants';
10
10
  import { stringFromCodePoint } from 'common/input/TextDecoder';
@@ -212,13 +212,13 @@ export class BufferLine implements IBufferLine {
212
212
  * Since the input handler see the incoming chars as UTF32 codepoints,
213
213
  * it gets an optimized access method.
214
214
  */
215
- public setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number, eAttrs: IExtendedAttrs): void {
216
- if (bg & BgFlags.HAS_EXTENDED) {
217
- this._extendedAttrs[index] = eAttrs;
215
+ public setCellFromCodepoint(index: number, codePoint: number, width: number, attrs: IAttributeData): void {
216
+ if (attrs.bg & BgFlags.HAS_EXTENDED) {
217
+ this._extendedAttrs[index] = attrs.extended;
218
218
  }
219
219
  this._data[index * CELL_SIZE + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT);
220
- this._data[index * CELL_SIZE + Cell.FG] = fg;
221
- this._data[index * CELL_SIZE + Cell.BG] = bg;
220
+ this._data[index * CELL_SIZE + Cell.FG] = attrs.fg;
221
+ this._data[index * CELL_SIZE + Cell.BG] = attrs.bg;
222
222
  }
223
223
 
224
224
  /**
@@ -253,12 +253,12 @@ export class BufferLine implements IBufferLine {
253
253
  this._data[index * CELL_SIZE + Cell.CONTENT] = content;
254
254
  }
255
255
 
256
- public insertCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {
256
+ public insertCells(pos: number, n: number, fillCellData: ICellData): void {
257
257
  pos %= this.length;
258
258
 
259
259
  // handle fullwidth at pos: reset cell one to the left if pos is second cell of a wide char
260
260
  if (pos && this.getWidth(pos - 1) === 2) {
261
- this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
261
+ this.setCellFromCodepoint(pos - 1, 0, 1, fillCellData);
262
262
  }
263
263
 
264
264
  if (n < this.length - pos) {
@@ -277,11 +277,11 @@ export class BufferLine implements IBufferLine {
277
277
 
278
278
  // handle fullwidth at line end: reset last cell if it is first cell of a wide char
279
279
  if (this.getWidth(this.length - 1) === 2) {
280
- this.setCellFromCodePoint(this.length - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
280
+ this.setCellFromCodepoint(this.length - 1, 0, 1, fillCellData);
281
281
  }
282
282
  }
283
283
 
284
- public deleteCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {
284
+ public deleteCells(pos: number, n: number, fillCellData: ICellData): void {
285
285
  pos %= this.length;
286
286
  if (n < this.length - pos) {
287
287
  const cell = new CellData();
@@ -301,21 +301,21 @@ export class BufferLine implements IBufferLine {
301
301
  // - reset pos-1 if wide char
302
302
  // - reset pos if width==0 (previous second cell of a wide char)
303
303
  if (pos && this.getWidth(pos - 1) === 2) {
304
- this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
304
+ this.setCellFromCodepoint(pos - 1, 0, 1, fillCellData);
305
305
  }
306
306
  if (this.getWidth(pos) === 0 && !this.hasContent(pos)) {
307
- this.setCellFromCodePoint(pos, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
307
+ this.setCellFromCodepoint(pos, 0, 1, fillCellData);
308
308
  }
309
309
  }
310
310
 
311
- public replaceCells(start: number, end: number, fillCellData: ICellData, eraseAttr?: IAttributeData, respectProtect: boolean = false): void {
311
+ public replaceCells(start: number, end: number, fillCellData: ICellData, respectProtect: boolean = false): void {
312
312
  // full branching on respectProtect==true, hopefully getting fast JIT for standard case
313
313
  if (respectProtect) {
314
314
  if (start && this.getWidth(start - 1) === 2 && !this.isProtected(start - 1)) {
315
- this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
315
+ this.setCellFromCodepoint(start - 1, 0, 1, fillCellData);
316
316
  }
317
317
  if (end < this.length && this.getWidth(end - 1) === 2 && !this.isProtected(end)) {
318
- this.setCellFromCodePoint(end, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
318
+ this.setCellFromCodepoint(end, 0, 1, fillCellData);
319
319
  }
320
320
  while (start < end && start < this.length) {
321
321
  if (!this.isProtected(start)) {
@@ -328,11 +328,11 @@ export class BufferLine implements IBufferLine {
328
328
 
329
329
  // handle fullwidth at start: reset cell one to the left if start is second cell of a wide char
330
330
  if (start && this.getWidth(start - 1) === 2) {
331
- this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
331
+ this.setCellFromCodepoint(start - 1, 0, 1, fillCellData);
332
332
  }
333
333
  // handle fullwidth at last cell + 1: reset to empty cell if it is second part of a wide char
334
334
  if (end < this.length && this.getWidth(end - 1) === 2) {
335
- this.setCellFromCodePoint(end, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs());
335
+ this.setCellFromCodepoint(end, 0, 1, fillCellData);
336
336
  }
337
337
 
338
338
  while (start < end && start < this.length) {
@@ -508,16 +508,43 @@ export class BufferLine implements IBufferLine {
508
508
  }
509
509
  }
510
510
 
511
- public translateToString(trimRight: boolean = false, startCol: number = 0, endCol: number = this.length): string {
511
+ /**
512
+ * Translates the buffer line to a string.
513
+ *
514
+ * @param trimRight Whether to trim any empty cells on the right.
515
+ * @param startCol The column to start the string (0-based inclusive).
516
+ * @param endCol The column to end the string (0-based exclusive).
517
+ * @param outColumns if specified, this array will be filled with column numbers such that
518
+ * `returnedString[i]` is displayed at `outColumns[i]` column. `outColumns[returnedString.length]`
519
+ * is where the character following `returnedString` will be displayed.
520
+ *
521
+ * When a single cell is translated to multiple UTF-16 code units (e.g. surrogate pair) in the
522
+ * returned string, the corresponding entries in `outColumns` will have the same column number.
523
+ */
524
+ public translateToString(trimRight?: boolean, startCol?: number, endCol?: number, outColumns?: number[]): string {
525
+ startCol = startCol ?? 0;
526
+ endCol = endCol ?? this.length;
512
527
  if (trimRight) {
513
528
  endCol = Math.min(endCol, this.getTrimmedLength());
514
529
  }
530
+ if (outColumns) {
531
+ outColumns.length = 0;
532
+ }
515
533
  let result = '';
516
534
  while (startCol < endCol) {
517
535
  const content = this._data[startCol * CELL_SIZE + Cell.CONTENT];
518
536
  const cp = content & Content.CODEPOINT_MASK;
519
- result += (content & Content.IS_COMBINED_MASK) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR;
520
- startCol += (content >> Content.WIDTH_SHIFT) || 1; // always advance by 1
537
+ const chars = (content & Content.IS_COMBINED_MASK) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR;
538
+ result += chars;
539
+ if (outColumns) {
540
+ for (let i = 0; i < chars.length; ++i) {
541
+ outColumns.push(startCol);
542
+ }
543
+ }
544
+ startCol += (content >> Content.WIDTH_SHIFT) || 1; // always advance by at least 1
545
+ }
546
+ if (outColumns) {
547
+ outColumns.push(startCol);
521
548
  }
522
549
  return result;
523
550
  }
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { EventEmitter } from 'common/EventEmitter';
7
- import { Disposable } from 'common/Lifecycle';
7
+ import { Disposable, toDisposable } from 'common/Lifecycle';
8
8
  import { isMac } from 'common/Platform';
9
9
  import { CursorStyle, IDisposable } from 'common/Types';
10
10
  import { FontWeight, IOptionsService, ITerminalOptions } from 'common/services/Services';
@@ -86,6 +86,13 @@ export class OptionsService extends Disposable implements IOptionsService {
86
86
  this.rawOptions = defaultOptions;
87
87
  this.options = { ... defaultOptions };
88
88
  this._setupOptions();
89
+
90
+ // Clear out options that could link outside xterm.js as they could easily cause an embedder
91
+ // memory leak
92
+ this.register(toDisposable(() => {
93
+ this.rawOptions.linkHandler = null;
94
+ this.rawOptions.documentOverride = null;
95
+ }));
89
96
  }
90
97
 
91
98
  // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -81,6 +81,10 @@ export class Terminal extends CoreTerminal {
81
81
  this._onBell.fire();
82
82
  }
83
83
 
84
+ public input(data: string, wasUserInput: boolean = true): void {
85
+ this.coreService.triggerDataEvent(data, wasUserInput);
86
+ }
87
+
84
88
  /**
85
89
  * Resizes the terminal.
86
90
  *
@@ -134,6 +134,9 @@ export class Terminal extends Disposable implements ITerminalApi {
134
134
  this._publicOptions[propName] = options[propName];
135
135
  }
136
136
  }
137
+ public input(data: string, wasUserInput: boolean = true): void {
138
+ this._core.input(data, wasUserInput);
139
+ }
137
140
  public resize(columns: number, rows: number): void {
138
141
  this._verifyIntegers(columns, rows);
139
142
  this._core.resize(columns, rows);
@@ -963,6 +963,18 @@ declare module '@xterm/xterm' {
963
963
  */
964
964
  focus(): void;
965
965
 
966
+ /**
967
+ * Input data to application side. The data is treated the same way input
968
+ * typed into the terminal would (ie. the {@link onData} event will fire).
969
+ * @param data The data to forward to the application.
970
+ * @param wasUserInput Whether the input is genuine user input. This is true
971
+ * by default and triggers additionalbehavior like focus or selection
972
+ * clearing. Set this to false if the data sent should not be treated like
973
+ * user input would, for example passing an escape sequence to the
974
+ * application.
975
+ */
976
+ input(data: string, wasUserInput?: boolean): void;
977
+
966
978
  /**
967
979
  * Resizes the terminal. It's best practice to debounce calls to resize,
968
980
  * this will help ensure that the pty can respond to the resize event
@@ -1010,6 +1022,28 @@ declare module '@xterm/xterm' {
1010
1022
  */
1011
1023
  attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void;
1012
1024
 
1025
+ /**
1026
+ * Attaches a custom wheel event handler which is run before keys are
1027
+ * processed, giving consumers of xterm.js control over whether to proceed
1028
+ * or cancel terminal wheel events.
1029
+ * @param customWheelEventHandler The custom WheelEvent handler to attach.
1030
+ * This is a function that takes a WheelEvent, allowing consumers to stop
1031
+ * propagation and/or prevent the default action. The function returns
1032
+ * whether the event should be processed by xterm.js.
1033
+ *
1034
+ * @example A handler that prevents all wheel events while ctrl is held from
1035
+ * being processed.
1036
+ * ```ts
1037
+ * term.attachCustomWheelEventHandler(ev => {
1038
+ * if (ev.ctrlKey) {
1039
+ * return false;
1040
+ * }
1041
+ * return true;
1042
+ * });
1043
+ * ```
1044
+ */
1045
+ attachCustomWheelEventHandler(customWheelEventHandler: (event: WheelEvent) => boolean): void;
1046
+
1013
1047
  /**
1014
1048
  * Registers a link provider, allowing a custom parser to be used to match
1015
1049
  * and handle links. Multiple link providers can be used, they will be asked