@lvce-editor/file-search-worker 1.5.0 → 1.7.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.
@@ -18,6 +18,113 @@ const execute = (command, ...args) => {
18
18
  return fn(...args);
19
19
  };
20
20
 
21
+ const Directory$1 = 3;
22
+ const File$1 = 7;
23
+
24
+ const Slash$1 = '/';
25
+
26
+ const Slash = Slash$1;
27
+
28
+ const state$4 = {
29
+ files: Object.create(null)
30
+ };
31
+ const getDirent = uri => {
32
+ return state$4.files[uri];
33
+ };
34
+ const readFile = uri => {
35
+ const dirent = getDirent(uri);
36
+ if (!dirent) {
37
+ throw new Error(`File not found: ${uri}`);
38
+ }
39
+ if (dirent.type !== File$1) {
40
+ throw new Error('file is a directory');
41
+ }
42
+ return dirent.content;
43
+ };
44
+ const ensureParentDir = uri => {
45
+ const startIndex = 0;
46
+ let endIndex = uri.indexOf(Slash);
47
+ while (endIndex >= 0) {
48
+ const part = uri.slice(startIndex, endIndex + 1);
49
+ state$4.files[part] = {
50
+ type: Directory$1,
51
+ content: ''
52
+ };
53
+ endIndex = uri.indexOf(Slash, endIndex + 1);
54
+ }
55
+ };
56
+ const writeFile = (uri, content) => {
57
+ const dirent = getDirent(uri);
58
+ if (dirent) {
59
+ dirent.content = content;
60
+ } else {
61
+ ensureParentDir(uri);
62
+ state$4.files[uri] = {
63
+ type: File$1,
64
+ content
65
+ };
66
+ }
67
+ };
68
+ const mkdir = uri => {
69
+ if (!uri.endsWith(Slash)) {
70
+ uri += Slash;
71
+ }
72
+ ensureParentDir(uri);
73
+ state$4.files[uri] = {
74
+ type: Directory$1,
75
+ content: ''
76
+ };
77
+ };
78
+ const readDirWithFileTypes = uri => {
79
+ if (!uri.endsWith(Slash)) {
80
+ uri += Slash;
81
+ }
82
+ const dirents = [];
83
+ for (const [key, value] of Object.entries(state$4.files)) {
84
+ if (key.startsWith(uri)) {
85
+ // @ts-ignore
86
+ switch (value.type) {
87
+ case Directory$1:
88
+ if (!key.slice(0, -1).includes(Slash, uri.length) && key !== `${uri}/` && key !== uri) {
89
+ dirents.push({
90
+ // @ts-ignore
91
+ type: value.type,
92
+ name: key.slice(uri.length, -1)
93
+ });
94
+ }
95
+ break;
96
+ case File$1:
97
+ if (!key.includes(Slash, uri.length + 1)) {
98
+ dirents.push({
99
+ // @ts-ignore
100
+ type: value.type,
101
+ name: key.slice(uri.length)
102
+ });
103
+ }
104
+ break;
105
+ }
106
+ }
107
+ }
108
+ return dirents;
109
+ };
110
+ const getBlobUrl = uri => {
111
+ const content = readFile(uri);
112
+ const blob = new Blob([content]);
113
+ const url = URL.createObjectURL(blob);
114
+ return url;
115
+ };
116
+ const getBlob = uri => {
117
+ const content = readFile(uri);
118
+ const blob = new Blob([content]);
119
+ return blob;
120
+ };
121
+ const chmod = () => {
122
+ throw new Error('[memfs] chmod not implemented');
123
+ };
124
+ const getFiles = () => {
125
+ return state$4.files;
126
+ };
127
+
21
128
  const searchFile$3 = async (workspace, root) => {
22
129
  return [];
23
130
  };
@@ -499,6 +606,193 @@ const searchFile$1 = async uri => {
499
606
  return all;
500
607
  };
501
608
 
609
+ const Diagonal = 1;
610
+ const Left = 2;
611
+
612
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
613
+
614
+ const createTable = size => {
615
+ const table = [];
616
+ for (let i = 0; i < size; i++) {
617
+ const row = new Uint8Array(size);
618
+ table.push(row);
619
+ }
620
+ return table;
621
+ };
622
+ const EmptyMatches = [];
623
+ const Dash = '-';
624
+ const Dot = '.';
625
+ const EmptyString = '';
626
+ const Space = ' ';
627
+ const Underline = '_';
628
+ const T = 't';
629
+ const isLowerCase = char => {
630
+ return char === char.toLowerCase();
631
+ };
632
+ const isUpperCase = char => {
633
+ return char === char.toUpperCase();
634
+ };
635
+
636
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
637
+ const isGap = (columnCharBefore, columnChar) => {
638
+ switch (columnCharBefore) {
639
+ case Dash:
640
+ case Underline:
641
+ case EmptyString:
642
+ case T:
643
+ case Space:
644
+ case Dot:
645
+ return true;
646
+ }
647
+ if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
648
+ return true;
649
+ }
650
+ return false;
651
+ };
652
+
653
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
654
+ const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch) => {
655
+ if (rowCharLow !== columnCharLow) {
656
+ return -1;
657
+ }
658
+ const isMatch = rowChar === columnChar;
659
+ if (isMatch) {
660
+ if (isDiagonalMatch) {
661
+ return 8;
662
+ }
663
+ if (isGap(columnCharBefore, columnChar)) {
664
+ return 8;
665
+ }
666
+ return 5;
667
+ }
668
+ if (isGap(columnCharBefore, columnChar)) {
669
+ return 8;
670
+ }
671
+ return 5;
672
+ };
673
+
674
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
675
+
676
+ const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
677
+ while (patternPos < patternLen && wordPos < wordLen) {
678
+ if (patternLow[patternPos] === wordLow[wordPos]) {
679
+ patternPos += 1;
680
+ }
681
+ wordPos += 1;
682
+ }
683
+ return patternPos === patternLen; // pattern must be exhausted
684
+ };
685
+
686
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
687
+ const traceHighlights = (table, arrows, patternLength, wordLength) => {
688
+ let row = patternLength;
689
+ let column = wordLength;
690
+ const matches = [];
691
+ while (row >= 1 && column >= 1) {
692
+ const arrow = arrows[row][column];
693
+ if (arrow === Left) {
694
+ column--;
695
+ } else if (arrow === Diagonal) {
696
+ row--;
697
+ column--;
698
+ const start = column + 1;
699
+ while (row >= 1 && column >= 1) {
700
+ const arrow = arrows[row][column];
701
+ if (arrow === Left) {
702
+ break;
703
+ }
704
+ if (arrow === Diagonal) {
705
+ row--;
706
+ column--;
707
+ }
708
+ }
709
+ const end = column;
710
+ matches.unshift(end, start);
711
+ }
712
+ }
713
+ matches.unshift(table[patternLength][wordLength - 1]);
714
+ return matches;
715
+ };
716
+
717
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
718
+ const gridSize = 128;
719
+ const table = createTable(gridSize);
720
+ const arrows = createTable(gridSize);
721
+ const fuzzySearch = (pattern, word) => {
722
+ const patternLength = Math.min(pattern.length, gridSize - 1);
723
+ const wordLength = Math.min(word.length, gridSize - 1);
724
+ const patternLower = pattern.toLowerCase();
725
+ const wordLower = word.toLowerCase();
726
+ if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
727
+ return EmptyMatches;
728
+ }
729
+ let strongMatch = false;
730
+ for (let row = 1; row < patternLength + 1; row++) {
731
+ const rowChar = pattern[row - 1];
732
+ const rowCharLow = patternLower[row - 1];
733
+ for (let column = 1; column < wordLength + 1; column++) {
734
+ const columnChar = word[column - 1];
735
+ const columnCharLow = wordLower[column - 1];
736
+ const columnCharBefore = word[column - 2] || '';
737
+ const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
738
+ const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch);
739
+ if (row === 1 && score > 5) {
740
+ strongMatch = true;
741
+ }
742
+ let diagonalScore = score + table[row - 1][column - 1];
743
+ if (isDiagonalMatch && score !== -1) {
744
+ diagonalScore += 2;
745
+ }
746
+ const leftScore = table[row][column - 1];
747
+ if (leftScore > diagonalScore) {
748
+ table[row][column] = leftScore;
749
+ arrows[row][column] = Left;
750
+ } else {
751
+ table[row][column] = diagonalScore;
752
+ arrows[row][column] = Diagonal;
753
+ }
754
+ }
755
+ }
756
+ if (!strongMatch) {
757
+ return EmptyMatches;
758
+ }
759
+ const highlights = traceHighlights(table, arrows, patternLength, wordLength);
760
+ return highlights;
761
+ };
762
+
763
+ const filterQuickPickItem = (pattern, word) => {
764
+ const matches = fuzzySearch(pattern, word);
765
+ return matches;
766
+ };
767
+
768
+ const getBaseName = path => {
769
+ return path.slice(path.lastIndexOf('/') + 1);
770
+ };
771
+ const emptyMatches = [];
772
+ const convertToPick = item => {
773
+ return {
774
+ pick: item,
775
+ matches: emptyMatches
776
+ };
777
+ };
778
+ const filterQuickPickItems = (items, value) => {
779
+ if (!value) {
780
+ return items.map(convertToPick);
781
+ }
782
+ const results = [];
783
+ for (const item of items) {
784
+ const baseName = getBaseName(item);
785
+ const matches = filterQuickPickItem(value, baseName);
786
+ if (matches.length > 0) {
787
+ results.push({
788
+ pick: item,
789
+ matches
790
+ });
791
+ }
792
+ }
793
+ return results;
794
+ };
795
+
502
796
  const getFileSearchRipGrepArgs = () => {
503
797
  const ripGrepArgs = ['--files', '--sort-files'];
504
798
  return ripGrepArgs;
@@ -903,7 +1197,7 @@ const splitLines$1 = lines => {
903
1197
 
904
1198
  // TODO create direct connection from electron to file search worker using message ports
905
1199
 
906
- const searchFile = async (path, value) => {
1200
+ const searchFile = async (path, value, prepare) => {
907
1201
  const ripGrepArgs = getFileSearchRipGrepArgs();
908
1202
  const options = {
909
1203
  ripGrepArgs,
@@ -912,14 +1206,26 @@ const searchFile = async (path, value) => {
912
1206
  };
913
1207
  const stdout = await invoke('SearchFile.searchFile', options);
914
1208
  const lines = splitLines$1(stdout);
915
- return lines;
1209
+ if (!prepare) {
1210
+ return lines;
1211
+ }
1212
+ const filtered = filterQuickPickItems(lines, value);
1213
+ return filtered;
916
1214
  };
917
1215
 
918
1216
  const commandMap = {
919
1217
  'SearchFile.searchFile': searchFile$3,
920
1218
  'SearchFile.searchFileWithRipGrep': searchFile,
921
1219
  'SearchFile.searchFileWithHtml': searchFile$1,
922
- 'SearchFile.searchFileWithFetch': searchFile$2
1220
+ 'SearchFile.searchFileWithFetch': searchFile$2,
1221
+ 'FileSystemMemory.readFile': readFile,
1222
+ 'FileSystemMemory.writeFile': writeFile,
1223
+ 'FileSystemMemory.mkdir': mkdir,
1224
+ 'FileSystemMemory.readDirWithFileTypes': readDirWithFileTypes,
1225
+ 'FileSystemMemory.getBlobUrl': getBlobUrl,
1226
+ 'FileSystemMemory.getBlob': getBlob,
1227
+ 'FileSystemMemory.chmod': chmod,
1228
+ 'FileSystemMemory.getFiles': getFiles
923
1229
  };
924
1230
 
925
1231
  const requiresSocket = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/file-search-worker",
3
- "version": "1.5.0",
3
+ "version": "1.7.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
  }