Skip to content

Commit f1d3dc0

Browse files
committed
Code clean up
1 parent 693069d commit f1d3dc0

File tree

1 file changed

+94
-78
lines changed

1 file changed

+94
-78
lines changed

addons/addon-search/src/SearchAddon.ts

Lines changed: 94 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ interface IHighlight extends IDisposable {
4747
decoration: IDecoration;
4848
match: ISearchResult;
4949
}
50-
// just a wrapper around boolean so we can keep a reference to value
50+
// just a wrapper around boolean so we can keep a reference to boolean value
5151
// to make it clear: the goal is to pass a boolean by reference not value
52-
type CancelSearchSignal = {
52+
interface ICancelSearchSignal{
5353
value: boolean;
54-
};
54+
}
5555

56-
type ChunckSearchDirection = 'up'|'down';
56+
type ChunkSearchDirection = 'up'|'down';
5757

5858
const NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\;:"\',./<>?';
5959
const DEFAULT_HIGHLIGHT_LIMIT = 1000;
@@ -70,18 +70,18 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
7070
private _searchOptions: ISearchOptions | undefined;
7171
private _debounceTimeout: number | undefined;
7272
private _searchCompleted: boolean = true;
73-
private _cancelSearchSignal: CancelSearchSignal = { value:false };
73+
private _cancelSearchSignal: ICancelSearchSignal = { value:false };
7474
/**
75-
* Number of matches in each chunck
75+
* Number of matches in each chunk
7676
*/
77-
private _chunckSize: number = 200;
77+
private _chunkSize: number = 200;
7878
/**
7979
* Time in ms
8080
* 1 ms seems to work fine as we just need to let other parts of the code to take over
81-
* and return here when other work is done
81+
* and return here when their work is done
8282
*/
83-
private _timeBetweenChunckOperations = 1;
84-
private _chunckSearchDirection: ChunckSearchDirection = 'down';
83+
private _timeBetweenChunkOperations = 1;
84+
8585
/**
8686
* This should be high enough so not to trigger a lot of searches
8787
* and subsequently a lot of canceled searches which clean up their own
@@ -97,7 +97,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
9797
* We memoize the calls into an array that has a time based ttl.
9898
* _linesCache is also invalidated when the terminal cursor moves.
9999
*/
100-
private _linesCache: LineCacheEntry[] | undefined;
100+
private _linesCache: LineCacheEntry[] = [];
101101

102102
private readonly _onDidChangeResults = this._register(new Emitter<{ resultIndex: number, resultCount: number,searchCompleted: boolean }>());
103103
public readonly onDidChangeResults = this._onDidChangeResults.event;
@@ -135,7 +135,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
135135
}
136136

137137
/**
138-
* The array needs to be in descending Marker ID order.
138+
* The array needs to be in descending Marker ID order.
139139
*
140140
* that way we get the smallest ID fist using pop
141141
*
@@ -145,16 +145,16 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
145145
*/
146146
private _iterateToDisposeDecoration(matchesWithHighlightApplied: IHighlight[]): void{
147147
setTimeout(()=>{
148-
this._chunckDisposeDecoration(matchesWithHighlightApplied);
148+
this._chunkDisposeDecoration(matchesWithHighlightApplied);
149149

150150
if (matchesWithHighlightApplied.length>0){
151151
this._iterateToDisposeDecoration(matchesWithHighlightApplied);
152152
}
153-
},this._timeBetweenChunckOperations);
153+
},this._timeBetweenChunkOperations);
154154
}
155-
private _chunckDisposeDecoration(matchesWithHighlightApplied: IHighlight[]): void{
155+
private _chunkDisposeDecoration(matchesWithHighlightApplied: IHighlight[]): void{
156156

157-
const numberOfElementsToDispose = this._chunckSize > matchesWithHighlightApplied.length ? matchesWithHighlightApplied.length : this._chunckSize;
157+
const numberOfElementsToDispose = this._chunkSize > matchesWithHighlightApplied.length ? matchesWithHighlightApplied.length : this._chunkSize;
158158

159159
for (let i=0;i<numberOfElementsToDispose;i++){
160160
matchesWithHighlightApplied.pop()?.dispose();
@@ -206,13 +206,12 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
206206
window.clearTimeout(this._debounceTimeout);
207207

208208
this._debounceTimeout = setTimeout(()=>{
209-
// regex search modifies the line buffer
209+
// regex search modifies the line cache
210210
// if the previous search was regex we need to clear it
211211
if (wasLastSearchRegex===true){
212-
console.log("destroying cache")
213212
this._destroyLinesCache();
214213
}
215-
this._cancelSearchSignal = { value:false };
214+
this._cancelSearchSignal = { value: false };
216215
this._searchCompleted = false;
217216
this.clearDecorations(true);
218217
this._matches = [];
@@ -265,73 +264,85 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
265264
this._fireResults();
266265
}
267266

268-
private _findAllMatches(term: string,cancelSearchSignal: CancelSearchSignal): void {
267+
private _findAllMatches(term: string,cancelSearchSignal: ICancelSearchSignal): void {
269268

270269

271-
const chunckSearchIterator = this._chunckSearchGenerator(term,cancelSearchSignal);
272-
this._iterate(chunckSearchIterator,0);
270+
const chunkSearchIterator = this._chunkSearchGenerator(term,cancelSearchSignal);
271+
this._iterate(chunkSearchIterator,0);
273272
}
274273

275-
private _iterate(searchIterator: Generator<{direction: string,chunckSize: number}>,chunckIndex: number): void{
274+
/**
275+
* @param searchIterator
276+
* @param chunkIndex only used to select first match when first chunk comes in
277+
*/
278+
private _iterate(searchIterator: Generator<{direction: string,chunkSize: number}>,chunkIndex: number): void{
276279
setTimeout(()=>{
280+
277281
const iteratorResult = searchIterator.next();
278-
if (chunckIndex===0){
282+
283+
if (chunkIndex===0){
279284
this._moveToTheNextMatch(false);
280285
}
286+
281287
if (iteratorResult.done === false){
282-
const { direction,chunckSize } = iteratorResult.value;
283-
const startIndex = direction === 'down' ? this._matches.length - chunckSize : 0;
284-
const endIndex = direction ==='down' ? this._matches.length : chunckSize;
285-
this._highlightChunck(startIndex,endIndex);
288+
const { direction,chunkSize } = iteratorResult.value;
289+
290+
const startIndex = direction === 'down' ? this._matches.length - chunkSize : 0;
291+
const endIndex = direction ==='down' ? this._matches.length : chunkSize;
292+
293+
this._highlightChunk(startIndex,endIndex);
294+
// adjust match index with the growing result
286295
if (direction==='up'){
287-
this._currentMatchIndex += chunckSize;
296+
this._currentMatchIndex += chunkSize;
288297
this._fireResults();
289298
}
290-
this._iterate(searchIterator,++chunckIndex);
299+
this._iterate(searchIterator,++chunkIndex);
291300
}
292-
else if (iteratorResult.value !== false){
293-
const { direction,chunckSize } = iteratorResult.value;
294-
const startIndex = direction === 'down' ? this._matches.length - chunckSize : 0;
295-
const endIndex = direction ==='down' ? this._matches.length : chunckSize;
296-
this._highlightChunck(startIndex,endIndex);
301+
else if (iteratorResult.value !== false){ // search finished without being cancelled
302+
const { direction,chunkSize } = iteratorResult.value;
303+
304+
const startIndex = direction === 'down' ? this._matches.length - chunkSize : 0;
305+
const endIndex = direction ==='down' ? this._matches.length : chunkSize;
306+
307+
this._highlightChunk(startIndex,endIndex);
308+
297309
if (direction==='up'){
298-
this._currentMatchIndex += chunckSize;
310+
this._currentMatchIndex += chunkSize;
299311
}
300312
this._searchCompleted = true;
301313
this._fireResults();
302314
}
303315

304-
},this._timeBetweenChunckOperations);
316+
},this._timeBetweenChunkOperations);
305317
}
306318
private _fireResults(): void {
307319
if (this._searchOptions?.decorations){
308320
this._onDidChangeResults.fire({ resultIndex:this._currentMatchIndex, resultCount: this._matches.length,searchCompleted: this._searchCompleted });
309321
}
310322
}
311-
private *_chunckSearchGenerator(term: string,cancelSearchSignal: CancelSearchSignal): Generator<{direction: string,chunckSize: number}>{
323+
private *_chunkSearchGenerator(term: string,cancelSearchSignal: ICancelSearchSignal): Generator<{direction: string,chunkSize: number}>{
312324

313325
const rowIndex = this._terminal!.buffer.active.viewportY;
314326

315-
let searchDirection: ChunckSearchDirection = 'down';
327+
let searchDirection: ChunkSearchDirection = 'down';
316328

317329
let downDirectionLastResult = this._find(term, rowIndex, 0,'down');
318330
let upDirectionLastResult = this._find(term, rowIndex - 1, this._terminal!.cols,'up');
319331

320332

321333
searchDirection = downDirectionLastResult !== undefined ? 'down' : 'up';
322334

323-
let currentChunckMatches: ISearchResult[] = [];
335+
let currentChunkMatches: ISearchResult[] = [];
324336

325337
while (downDirectionLastResult !== undefined || upDirectionLastResult !== undefined) {
326338

327339
if (cancelSearchSignal.value === true){
328340
return false;
329341
}
330342

331-
332343
if (downDirectionLastResult !==undefined && searchDirection==='down'){
333344

334-
currentChunckMatches.push(downDirectionLastResult);
345+
currentChunkMatches.push(downDirectionLastResult);
335346

336347
downDirectionLastResult = this._find(
337348
term,
@@ -340,44 +351,54 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
340351
downDirectionLastResult.col + downDirectionLastResult.term.length >= this._terminal!.cols ? 0 : downDirectionLastResult!.col + 1,
341352
'down'
342353
);
354+
343355
} else if (upDirectionLastResult !== undefined && searchDirection === 'up'){
344-
currentChunckMatches.push(upDirectionLastResult);
356+
357+
currentChunkMatches.push(upDirectionLastResult);
358+
345359
upDirectionLastResult = this._find(
346360
term,
347-
// using previous term length will cause problems with regex
348361
upDirectionLastResult.row,
349362
upDirectionLastResult.col - 1,
350363
'up'
351364
);
352365
}
353366

354-
if (this._matches.length + currentChunckMatches.length >= this._highlightLimit) {
367+
if (this._matches.length + currentChunkMatches.length >= this._highlightLimit) {
368+
355369
if (searchDirection==='down'){
356-
this._matches.push(...currentChunckMatches);
370+
this._matches.push(...currentChunkMatches);
371+
357372
} else {
358-
currentChunckMatches.reverse();
359-
this._matches.unshift(...currentChunckMatches);// horible for performance just used temoprarly
373+
currentChunkMatches.reverse();
374+
this._matches.unshift(...currentChunkMatches);// bad for performance just used temoprarly
375+
360376
}
361377

362-
const doneReturn = { direction:searchDirection,chunckSize:currentChunckMatches.length };
363-
currentChunckMatches=[];
378+
const doneReturn = { direction:searchDirection,chunkSize:currentChunkMatches.length };
379+
380+
currentChunkMatches=[];
381+
364382
return doneReturn;
365383
}
366384

367385
if (
368-
(currentChunckMatches.length > 0 && currentChunckMatches.length % this._chunckSize === 0) ||
369-
(downDirectionLastResult === undefined && searchDirection === 'down') ||
370-
(upDirectionLastResult === undefined && searchDirection ==='up')
371-
) {
386+
(currentChunkMatches.length > 0 && currentChunkMatches.length % this._chunkSize === 0) ||
387+
(downDirectionLastResult === undefined && searchDirection === 'down') ||
388+
(upDirectionLastResult === undefined && searchDirection ==='up')
389+
)
390+
{
372391
if (searchDirection==='down'){
373-
this._matches.push(...currentChunckMatches);
392+
this._matches.push(...currentChunkMatches);
393+
374394
} else {
375-
currentChunckMatches.reverse();
376-
this._matches.unshift(...currentChunckMatches);// horible for performance just used temoprarly
395+
currentChunkMatches.reverse();
396+
this._matches.unshift(...currentChunkMatches);// bad for performance just used temoprarly
397+
377398
}
378399

379-
const yieldReturn = { direction:searchDirection,chunckSize:currentChunckMatches.length };
380-
currentChunckMatches=[];
400+
const yieldReturn = { direction:searchDirection,chunkSize:currentChunkMatches.length };
401+
currentChunkMatches=[];
381402
yield yieldReturn;
382403

383404
searchDirection = searchDirection === 'down' ? 'up':'down';
@@ -388,12 +409,13 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
388409
return true;
389410
}
390411

391-
private _highlightChunck(startIndex: number,endIndex: number): void{
412+
private _highlightChunk(startIndex: number,endIndex: number): void{
392413

393414
for (let i=startIndex; i < endIndex ;i++) {
394415

395416
const match = this._matches[i];
396417
const decoration = this._createResultDecoration(match);
418+
397419
if (decoration) {
398420
this._highlightedLines.add(decoration.marker.line);
399421
this._matchesWithHighlightApplied.push({ decoration, match, dispose() { decoration.dispose(); } });
@@ -403,7 +425,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
403425
}
404426

405427

406-
private _find(term: string, startRow: number, startCol: number,direction: ChunckSearchDirection): ISearchResult | undefined {
428+
private _find(term: string, startRow: number, startCol: number,direction: ChunkSearchDirection): ISearchResult | undefined {
407429
if (!this._terminal || !term || term.length === 0) {
408430
return undefined;
409431
}
@@ -437,8 +459,8 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
437459
let resultAtOtherRowsScanColumnsRightToLeft: ISearchResult | undefined = undefined;
438460

439461
if (resultAtRowAndToTheLeftOfColumn === undefined){
440-
441-
for (let y = this._searchOptions?.regex===true ? startRow: startRow - 1 ; y >= 0; y--) {
462+
const startFrom = this._searchOptions?.regex===true ? startRow: startRow - 1;
463+
for (let y = startFrom; y >= 0; y--) {
442464
for (let j = this._terminal!.cols; j >= 0 ; j-- ){
443465
resultAtOtherRowsScanColumnsRightToLeft = this._findInLine(term, { startRow: y,startCol: j },true);
444466
if (resultAtOtherRowsScanColumnsRightToLeft) {
@@ -470,41 +492,35 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
470492
const row = searchPosition.startRow;
471493
const col = searchPosition.startCol;
472494

473-
// console.log( translateBufferLineToStringWithWrap(terminal,row, true));
474-
// // Ignore wrapped lines, only consider on unwrapped line (first row of command string).
475-
// if ( terminal.buffer.active.getLine(row)?.isWrapped === true) {
476-
// // console.log("ignored a wrapped line")
477-
// // return;
478-
// }
479-
480495
let cache = this._linesCache?.[row];
481496
if (!cache) {
482497
cache = translateBufferLineToStringWithWrap(terminal,row, true);
483-
// console.log("is wrapped: " + (terminal.buffer.active.getLine(row)?.isWrapped === true))
484-
// console.log("string line: "+cache[0]+" string length:"+cache[0].length +" offset: "+cache[1]);
485-
if (this._linesCache) {
486-
this._linesCache[row] = cache;
487-
}
498+
this._linesCache[row] = cache;
488499
}
489500
const [stringLine, offsets] = cache;
490501

491502
let offset = bufferColsToStringOffset(terminal, row, col);
492-
// console.log("direction "+scanRightToLeft+" rows "+row+" "+"column: "+col+" offset"+offset+" total view port cols" +this._terminal!.cols);
493-
const searchTerm = this._searchOptions?.caseSensitive ? term : term.toLowerCase();
494-
const searchStringLine = this._searchOptions?.caseSensitive ? stringLine : stringLine.toLowerCase();
495503

496504
if (offset > stringLine.length){
497505
offset = stringLine.length;
498506
}
507+
508+
const searchTerm = this._searchOptions?.caseSensitive ? term : term.toLowerCase();
509+
const searchStringLine = this._searchOptions?.caseSensitive ? stringLine : stringLine.toLowerCase();
510+
499511
let resultIndex = -1;
512+
500513
if (this._searchOptions?.regex) {
514+
501515
const searchRegex = RegExp(searchTerm, 'g');
516+
502517
if (scanRightToLeft === false){
503518
const foundTerm: RegExpExecArray | null = searchRegex.exec(searchStringLine.slice(offset));
504519
if (foundTerm && foundTerm[0].length > 0) {
505520
resultIndex = offset + (searchRegex.lastIndex - foundTerm[0].length);
506521
term = foundTerm[0];
507522
}
523+
508524
} else {
509525
const foundTerm: RegExpExecArray | null = searchRegex.exec(searchStringLine.slice(offset));
510526
if (foundTerm && foundTerm[0].length > 0) {

0 commit comments

Comments
 (0)