@xterm/addon-search 0.16.0-beta.106 → 0.16.0-beta.107

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xterm/addon-search",
3
- "version": "0.16.0-beta.106",
3
+ "version": "0.16.0-beta.107",
4
4
  "author": {
5
5
  "name": "The xterm.js authors",
6
6
  "url": "https://xtermjs.org/"
@@ -22,7 +22,7 @@
22
22
  "start": "node ../../demo/start"
23
23
  },
24
24
  "peerDependencies": {
25
- "@xterm/xterm": "^5.6.0-beta.106"
25
+ "@xterm/xterm": "^5.6.0-beta.107"
26
26
  },
27
- "commit": "e29c2360e7f98805ae00a9c8591871068cab7eb5"
27
+ "commit": "e9c547c1c6b67e9f09c24ccc007e19305f536e60"
28
28
  }
@@ -58,6 +58,11 @@ interface IHighlight extends IDisposable {
58
58
  match: ISearchResult;
59
59
  }
60
60
 
61
+ interface IMultiHighlight extends IDisposable {
62
+ decorations: IDecoration[];
63
+ match: ISearchResult;
64
+ }
65
+
61
66
  const NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\;:"\',./<>?';
62
67
  const LINES_CACHE_TIME_TO_LIVE = 15 * 1000; // 15 secs
63
68
  const DEFAULT_HIGHLIGHT_LIMIT = 1000;
@@ -67,7 +72,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
67
72
  private _cachedSearchTerm: string | undefined;
68
73
  private _highlightedLines: Set<number> = new Set();
69
74
  private _highlightDecorations: IHighlight[] = [];
70
- private _selectedDecoration: MutableDisposable<IHighlight> = this._register(new MutableDisposable());
75
+ private _selectedDecoration: MutableDisposable<IMultiHighlight> = this._register(new MutableDisposable());
71
76
  private _highlightLimit: number;
72
77
  private _lastSearchOptions: ISearchOptions | undefined;
73
78
  private _highlightTimeout: number | undefined;
@@ -179,14 +184,20 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
179
184
  );
180
185
  }
181
186
  for (const match of searchResultsWithHighlight) {
182
- const decoration = this._createResultDecoration(match, searchOptions.decorations!);
183
- if (decoration) {
184
- this._highlightedLines.add(decoration.marker.line);
185
- this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });
187
+ const decorations = this._createResultDecorations(match, searchOptions.decorations!, false);
188
+ if (decorations) {
189
+ for (const decoration of decorations) {
190
+ this._storeDecoration(decoration, match);
191
+ }
186
192
  }
187
193
  }
188
194
  }
189
195
 
196
+ private _storeDecoration(decoration: IDecoration, match: ISearchResult): void {
197
+ this._highlightedLines.add(decoration.marker.line);
198
+ this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });
199
+ }
200
+
190
201
  private _find(term: string, startRow: number, startCol: number, searchOptions?: ISearchOptions): ISearchResult | undefined {
191
202
  if (!this._terminal || !term || term.length === 0) {
192
203
  this._terminal?.clearSelection();
@@ -666,25 +677,9 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
666
677
  }
667
678
  terminal.select(result.col, result.row, result.size);
668
679
  if (options) {
669
- const marker = terminal.registerMarker(-terminal.buffer.active.baseY - terminal.buffer.active.cursorY + result.row);
670
- if (marker) {
671
- const decoration = terminal.registerDecoration({
672
- marker,
673
- x: result.col,
674
- width: result.size,
675
- backgroundColor: options.activeMatchBackground,
676
- layer: 'top',
677
- overviewRulerOptions: {
678
- color: options.activeMatchColorOverviewRuler
679
- }
680
- });
681
- if (decoration) {
682
- const disposables: IDisposable[] = [];
683
- disposables.push(marker);
684
- disposables.push(decoration.onRender((e) => this._applyStyles(e, options.activeMatchBorder, true)));
685
- disposables.push(decoration.onDispose(() => dispose(disposables)));
686
- this._selectedDecoration.value = { decoration, match: result, dispose() { decoration.dispose(); } };
687
- }
680
+ const decorations = this._createResultDecorations(result, options, true);
681
+ if (decorations) {
682
+ this._selectedDecoration.value = { decorations, match: result, dispose() { dispose(decorations); } };
688
683
  }
689
684
  }
690
685
 
@@ -724,28 +719,45 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
724
719
  * @param options the options for the decoration
725
720
  * @returns the {@link IDecoration} or undefined if the marker has already been disposed of
726
721
  */
727
- private _createResultDecoration(result: ISearchResult, options: ISearchDecorationOptions): IDecoration | undefined {
722
+ private _createResultDecorations(result: ISearchResult, options: ISearchDecorationOptions, isActiveResult: boolean): IDecoration[] | undefined {
728
723
  const terminal = this._terminal!;
729
- const marker = terminal.registerMarker(-terminal.buffer.active.baseY - terminal.buffer.active.cursorY + result.row);
730
- if (!marker) {
731
- return undefined;
732
- }
733
- const findResultDecoration = terminal.registerDecoration({
734
- marker,
735
- x: result.col,
736
- width: result.size,
737
- backgroundColor: options.matchBackground,
738
- overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {
739
- color: options.matchOverviewRuler,
740
- position: 'center'
724
+
725
+ // Gather decoration ranges for this match as it could wrap
726
+ const decorationRanges: [number, number, number][] = [];
727
+ let currentCol = result.col;
728
+ let remainingSize = result.size;
729
+ let markerOffset = -terminal.buffer.active.baseY - terminal.buffer.active.cursorY + result.row;
730
+ while (remainingSize > 0) {
731
+ const amountThisRow = Math.min(terminal.cols - currentCol, remainingSize);
732
+ decorationRanges.push([markerOffset, currentCol, amountThisRow]);
733
+ currentCol = 0;
734
+ remainingSize -= amountThisRow;
735
+ markerOffset++;
736
+ }
737
+
738
+ // Create the decorations
739
+ const decorations: IDecoration[] = [];
740
+ for (const range of decorationRanges) {
741
+ const marker = terminal.registerMarker(range[0]);
742
+ const decoration = terminal.registerDecoration({
743
+ marker,
744
+ x: range[1],
745
+ width: range[2],
746
+ backgroundColor: isActiveResult ? options.activeMatchBackground : options.matchBackground,
747
+ overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {
748
+ color: isActiveResult ? options.activeMatchColorOverviewRuler : options.matchOverviewRuler,
749
+ position: 'center'
750
+ }
751
+ });
752
+ if (decoration) {
753
+ const disposables: IDisposable[] = [];
754
+ disposables.push(marker);
755
+ disposables.push(decoration.onRender((e) => this._applyStyles(e, isActiveResult ? options.activeMatchBorder : options.matchBorder, false)));
756
+ disposables.push(decoration.onDispose(() => dispose(disposables)));
757
+ decorations.push(decoration);
741
758
  }
742
- });
743
- if (findResultDecoration) {
744
- const disposables: IDisposable[] = [];
745
- disposables.push(marker);
746
- disposables.push(findResultDecoration.onRender((e) => this._applyStyles(e, options.matchBorder, false)));
747
- disposables.push(findResultDecoration.onDispose(() => dispose(disposables)));
748
- }
749
- return findResultDecoration;
759
+ }
760
+
761
+ return decorations.length === 0 ? undefined : decorations;
750
762
  }
751
763
  }