@lvce-editor/file-search-worker 1.4.0 → 1.6.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.
- package/dist/fileSearchWorkerMain.js +197 -2
- package/package.json +2 -1
|
@@ -467,10 +467,14 @@ const getDirectoryHandle = async uri => {
|
|
|
467
467
|
}
|
|
468
468
|
return getDirectoryHandle(dirname$1);
|
|
469
469
|
};
|
|
470
|
+
const toIgnore = ['.git', 'node_modules', 'dist', 'dist2'];
|
|
470
471
|
const searchFilesRecursively = async (all, parent, handle) => {
|
|
471
472
|
const childHandles = await getChildHandles(handle);
|
|
472
473
|
const promises = [];
|
|
473
474
|
for (const childHandle of childHandles) {
|
|
475
|
+
if (toIgnore.includes(childHandle.name)) {
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
474
478
|
const absolutePath = parent + '/' + childHandle.name;
|
|
475
479
|
switch (childHandle.kind) {
|
|
476
480
|
case Directory:
|
|
@@ -495,6 +499,193 @@ const searchFile$1 = async uri => {
|
|
|
495
499
|
return all;
|
|
496
500
|
};
|
|
497
501
|
|
|
502
|
+
const Diagonal = 1;
|
|
503
|
+
const Left = 2;
|
|
504
|
+
|
|
505
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
506
|
+
|
|
507
|
+
const createTable = size => {
|
|
508
|
+
const table = [];
|
|
509
|
+
for (let i = 0; i < size; i++) {
|
|
510
|
+
const row = new Uint8Array(size);
|
|
511
|
+
table.push(row);
|
|
512
|
+
}
|
|
513
|
+
return table;
|
|
514
|
+
};
|
|
515
|
+
const EmptyMatches = [];
|
|
516
|
+
const Dash = '-';
|
|
517
|
+
const Dot = '.';
|
|
518
|
+
const EmptyString = '';
|
|
519
|
+
const Space = ' ';
|
|
520
|
+
const Underline = '_';
|
|
521
|
+
const T = 't';
|
|
522
|
+
const isLowerCase = char => {
|
|
523
|
+
return char === char.toLowerCase();
|
|
524
|
+
};
|
|
525
|
+
const isUpperCase = char => {
|
|
526
|
+
return char === char.toUpperCase();
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
530
|
+
const isGap = (columnCharBefore, columnChar) => {
|
|
531
|
+
switch (columnCharBefore) {
|
|
532
|
+
case Dash:
|
|
533
|
+
case Underline:
|
|
534
|
+
case EmptyString:
|
|
535
|
+
case T:
|
|
536
|
+
case Space:
|
|
537
|
+
case Dot:
|
|
538
|
+
return true;
|
|
539
|
+
}
|
|
540
|
+
if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
return false;
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
547
|
+
const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch) => {
|
|
548
|
+
if (rowCharLow !== columnCharLow) {
|
|
549
|
+
return -1;
|
|
550
|
+
}
|
|
551
|
+
const isMatch = rowChar === columnChar;
|
|
552
|
+
if (isMatch) {
|
|
553
|
+
if (isDiagonalMatch) {
|
|
554
|
+
return 8;
|
|
555
|
+
}
|
|
556
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
557
|
+
return 8;
|
|
558
|
+
}
|
|
559
|
+
return 5;
|
|
560
|
+
}
|
|
561
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
562
|
+
return 8;
|
|
563
|
+
}
|
|
564
|
+
return 5;
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
568
|
+
|
|
569
|
+
const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
|
|
570
|
+
while (patternPos < patternLen && wordPos < wordLen) {
|
|
571
|
+
if (patternLow[patternPos] === wordLow[wordPos]) {
|
|
572
|
+
patternPos += 1;
|
|
573
|
+
}
|
|
574
|
+
wordPos += 1;
|
|
575
|
+
}
|
|
576
|
+
return patternPos === patternLen; // pattern must be exhausted
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
580
|
+
const traceHighlights = (table, arrows, patternLength, wordLength) => {
|
|
581
|
+
let row = patternLength;
|
|
582
|
+
let column = wordLength;
|
|
583
|
+
const matches = [];
|
|
584
|
+
while (row >= 1 && column >= 1) {
|
|
585
|
+
const arrow = arrows[row][column];
|
|
586
|
+
if (arrow === Left) {
|
|
587
|
+
column--;
|
|
588
|
+
} else if (arrow === Diagonal) {
|
|
589
|
+
row--;
|
|
590
|
+
column--;
|
|
591
|
+
const start = column + 1;
|
|
592
|
+
while (row >= 1 && column >= 1) {
|
|
593
|
+
const arrow = arrows[row][column];
|
|
594
|
+
if (arrow === Left) {
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
if (arrow === Diagonal) {
|
|
598
|
+
row--;
|
|
599
|
+
column--;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
const end = column;
|
|
603
|
+
matches.unshift(end, start);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
matches.unshift(table[patternLength][wordLength - 1]);
|
|
607
|
+
return matches;
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
611
|
+
const gridSize = 128;
|
|
612
|
+
const table = createTable(gridSize);
|
|
613
|
+
const arrows = createTable(gridSize);
|
|
614
|
+
const fuzzySearch = (pattern, word) => {
|
|
615
|
+
const patternLength = Math.min(pattern.length, gridSize - 1);
|
|
616
|
+
const wordLength = Math.min(word.length, gridSize - 1);
|
|
617
|
+
const patternLower = pattern.toLowerCase();
|
|
618
|
+
const wordLower = word.toLowerCase();
|
|
619
|
+
if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
|
|
620
|
+
return EmptyMatches;
|
|
621
|
+
}
|
|
622
|
+
let strongMatch = false;
|
|
623
|
+
for (let row = 1; row < patternLength + 1; row++) {
|
|
624
|
+
const rowChar = pattern[row - 1];
|
|
625
|
+
const rowCharLow = patternLower[row - 1];
|
|
626
|
+
for (let column = 1; column < wordLength + 1; column++) {
|
|
627
|
+
const columnChar = word[column - 1];
|
|
628
|
+
const columnCharLow = wordLower[column - 1];
|
|
629
|
+
const columnCharBefore = word[column - 2] || '';
|
|
630
|
+
const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
|
|
631
|
+
const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch);
|
|
632
|
+
if (row === 1 && score > 5) {
|
|
633
|
+
strongMatch = true;
|
|
634
|
+
}
|
|
635
|
+
let diagonalScore = score + table[row - 1][column - 1];
|
|
636
|
+
if (isDiagonalMatch && score !== -1) {
|
|
637
|
+
diagonalScore += 2;
|
|
638
|
+
}
|
|
639
|
+
const leftScore = table[row][column - 1];
|
|
640
|
+
if (leftScore > diagonalScore) {
|
|
641
|
+
table[row][column] = leftScore;
|
|
642
|
+
arrows[row][column] = Left;
|
|
643
|
+
} else {
|
|
644
|
+
table[row][column] = diagonalScore;
|
|
645
|
+
arrows[row][column] = Diagonal;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
if (!strongMatch) {
|
|
650
|
+
return EmptyMatches;
|
|
651
|
+
}
|
|
652
|
+
const highlights = traceHighlights(table, arrows, patternLength, wordLength);
|
|
653
|
+
return highlights;
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const filterQuickPickItem = (pattern, word) => {
|
|
657
|
+
const matches = fuzzySearch(pattern, word);
|
|
658
|
+
return matches;
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
const getBaseName = path => {
|
|
662
|
+
return path.slice(path.lastIndexOf('/') + 1);
|
|
663
|
+
};
|
|
664
|
+
const emptyMatches = [];
|
|
665
|
+
const convertToPick = item => {
|
|
666
|
+
return {
|
|
667
|
+
pick: item,
|
|
668
|
+
matches: emptyMatches
|
|
669
|
+
};
|
|
670
|
+
};
|
|
671
|
+
const filterQuickPickItems = (items, value) => {
|
|
672
|
+
if (!value) {
|
|
673
|
+
return items.map(convertToPick);
|
|
674
|
+
}
|
|
675
|
+
const results = [];
|
|
676
|
+
for (const item of items) {
|
|
677
|
+
const baseName = getBaseName(item);
|
|
678
|
+
const matches = filterQuickPickItem(value, baseName);
|
|
679
|
+
if (matches.length > 0) {
|
|
680
|
+
results.push({
|
|
681
|
+
pick: item,
|
|
682
|
+
matches
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return results;
|
|
687
|
+
};
|
|
688
|
+
|
|
498
689
|
const getFileSearchRipGrepArgs = () => {
|
|
499
690
|
const ripGrepArgs = ['--files', '--sort-files'];
|
|
500
691
|
return ripGrepArgs;
|
|
@@ -899,7 +1090,7 @@ const splitLines$1 = lines => {
|
|
|
899
1090
|
|
|
900
1091
|
// TODO create direct connection from electron to file search worker using message ports
|
|
901
1092
|
|
|
902
|
-
const searchFile = async (path, value) => {
|
|
1093
|
+
const searchFile = async (path, value, prepare) => {
|
|
903
1094
|
const ripGrepArgs = getFileSearchRipGrepArgs();
|
|
904
1095
|
const options = {
|
|
905
1096
|
ripGrepArgs,
|
|
@@ -908,7 +1099,11 @@ const searchFile = async (path, value) => {
|
|
|
908
1099
|
};
|
|
909
1100
|
const stdout = await invoke('SearchFile.searchFile', options);
|
|
910
1101
|
const lines = splitLines$1(stdout);
|
|
911
|
-
|
|
1102
|
+
if (!prepare) {
|
|
1103
|
+
return lines;
|
|
1104
|
+
}
|
|
1105
|
+
const filtered = filterQuickPickItems(lines, value);
|
|
1106
|
+
return filtered;
|
|
912
1107
|
};
|
|
913
1108
|
|
|
914
1109
|
const commandMap = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/file-search-worker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/fileSearchWorkerMain.js",
|
|
6
6
|
"type": "module",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"author": "",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"dependencies": {
|
|
11
|
+
"@lvce-editor/fuzzy-search": "^1.0.0",
|
|
11
12
|
"idb": "^8.0.0"
|
|
12
13
|
}
|
|
13
14
|
}
|