Skip to content

Commit f0f3e06

Browse files
committed
Use regex capturing to enhance the search functionality
1 parent 776029e commit f0f3e06

File tree

1 file changed

+138
-72
lines changed

1 file changed

+138
-72
lines changed

src/CodeSnippetDisplay.tsx

Lines changed: 138 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,6 @@ export class CodeSnippetDisplay extends React.Component<
297297
const displayName = language + name;
298298

299299
// check if this snippet is one of the filtered snippets
300-
// console.log(displayName);
301300
if (
302301
this.state.searchValue !== '' &&
303302
Object.keys(this.state.matchIndices).includes(id.toString())
@@ -323,32 +322,82 @@ export class CodeSnippetDisplay extends React.Component<
323322
// const endIndex: number = startIndex + searchValue.length;
324323

325324
const elements = [];
326-
const boldIndices = this.state.matchIndices[id];
327-
for (const index of boldIndices) {
328-
if (index >= language.length) {
325+
const boldIndices = this.state.matchIndices[id].slice();
326+
// boldIndices.sort((a,b) => a - b);
327+
// for (const index of boldIndices) {
328+
// if (index >= language.length) {
329+
// elements.push(
330+
// displayName.substring(language.length, index)
331+
// );
332+
// elements.push(
333+
// <mark className={SEARCH_BOLD}>
334+
// {displayName.substring(index, index + 1)}
335+
// </mark>
336+
// );
337+
// }
338+
// }
339+
// console.log(boldIndices);
340+
// get first match index in the name
341+
let i = 0;
342+
while (i < boldIndices.length) {
343+
if (boldIndices[i] >= language.length) {
344+
elements.push(displayName.substring(language.length, boldIndices[i]));
345+
break;
346+
}
347+
i++;
348+
}
349+
350+
// when it matches the language
351+
if (i >= boldIndices.length) {
352+
return <span>{name}</span>;
353+
} else {
354+
let currIndex = boldIndices[i];
355+
let nextIndex;
356+
if (i < boldIndices.length - 1) {
357+
nextIndex = boldIndices[i + 1];
358+
} else {
359+
nextIndex = null;
360+
}
361+
while (nextIndex !== null) {
329362
elements.push(
330-
<span>{displayName.substring(language.length, index)}</span>
363+
<mark className={SEARCH_BOLD}>
364+
{displayName.substring(currIndex, currIndex + 1)}
365+
</mark>
331366
);
367+
elements.push(displayName.substring(currIndex + 1, nextIndex));
368+
currIndex = nextIndex;
369+
i++;
370+
if (i < boldIndices.length - 1) {
371+
nextIndex = boldIndices[i + 1];
372+
} else {
373+
nextIndex = null;
374+
}
375+
}
376+
377+
if (nextIndex === null) {
332378
elements.push(
333379
<mark className={SEARCH_BOLD}>
334-
{displayName.substring(index, index + 1)}
380+
{displayName.substring(currIndex, currIndex + 1)}
335381
</mark>
336382
);
383+
elements.push(
384+
displayName.substring(currIndex + 1, displayName.length)
385+
);
337386
}
338-
}
339-
340-
if (boldIndices[-1] < displayName.length) {
341-
elements.push(
342-
<span>
343-
{displayName.substring(boldIndices[-1] + 1, displayName.length)}
344-
</span>
345-
);
346-
}
347-
348-
if (elements.length === 0) {
349-
return <span>{name}</span>;
350-
} else {
387+
// if (boldIndices[boldIndices.length - 1] < displayName.length) {
388+
// elements.push(
389+
// // <span>
390+
// displayName.substring(boldIndices[boldIndices.length - 1] + 1, displayName.length)
391+
// // </span>
392+
// );
393+
// }
394+
// console.log(elements);
395+
396+
// if (elements.length === 0) {
397+
// return <span>{name}</span>;
398+
// } else {
351399
return <span>{elements}</span>;
400+
// }
352401
}
353402

354403
// if (endIndex <= language.length) {
@@ -392,8 +441,8 @@ export class CodeSnippetDisplay extends React.Component<
392441
new_element.setSelectionRange(0, new_element.value.length);
393442

394443
new_element.onblur = async (): Promise<void> => {
395-
console.log(target.innerHTML);
396-
console.log(new_element.value);
444+
// console.log(target.innerHTML);
445+
// console.log(new_element.value);
397446
if (target.innerHTML !== new_element.value) {
398447
const newPath = 'snippets/' + new_element.value + '.json';
399448
try {
@@ -1204,10 +1253,11 @@ export class CodeSnippetDisplay extends React.Component<
12041253
if (state.searchValue !== '' || state.filterTags.length !== 0) {
12051254
const newSnippets = props.codeSnippets.filter(codeSnippet => {
12061255
return (
1207-
(state.searchValue !== '' &&
1208-
codeSnippet.name.toLowerCase().includes(state.searchValue)) ||
1209-
(state.searchValue !== '' &&
1210-
codeSnippet.language.toLowerCase().includes(state.searchValue)) ||
1256+
Object.keys(state.matchIndices).includes(codeSnippet.id.toString()) ||
1257+
// (state.searchValue !== '' &&
1258+
// codeSnippet.name.toLowerCase().includes(state.searchValue)) ||
1259+
// (state.searchValue !== '' &&
1260+
// codeSnippet.language.toLowerCase().includes(state.searchValue)) ||
12111261
(codeSnippet.tags &&
12121262
codeSnippet.tags.some(tag => state.filterTags.includes(tag)))
12131263
);
@@ -1235,42 +1285,32 @@ export class CodeSnippetDisplay extends React.Component<
12351285
str: string,
12361286
char_list: string[]
12371287
): [number, number[]] {
1238-
const matches: { [key: string]: number } = {};
1288+
const match_indices = [];
12391289
let match = [];
12401290
while ((match = regex.exec(str))) {
1241-
matches[match[0]] = regex.lastIndex - 1;
1242-
// console.log(match);
1243-
// console.log("match found at " + match.index);
1244-
}
1291+
console.log(str);
1292+
console.log(match);
1293+
if (match) {
1294+
const matched_string = match[0];
1295+
const start_idx = match['index'];
1296+
for (const match_ch of match.slice(1)) {
1297+
const match_index = matched_string.indexOf(match_ch) + start_idx;
1298+
match_indices.push(match_index);
1299+
}
12451300

1246-
console.log(str);
1301+
// Object.keys(matches).length
1302+
// if (Object.keys(matches).length !== char_list.length) {
1303+
// return null;
1304+
// }
12471305

1248-
// Object.keys(matches).length
1249-
if (Object.keys(matches).length !== char_list.length) {
1250-
return null;
1306+
console.log(match_indices);
1307+
return [id, match_indices];
1308+
}
12511309
}
1252-
1253-
console.log(matches);
1254-
return [id, Object.values(matches)];
1310+
return null;
12551311
}
12561312

12571313
filterSnippets = (searchValue: string, filterTags: string[]): void => {
1258-
// remove space
1259-
const tempSearchValue = searchValue.replace(/ /g, '');
1260-
const char_list = tempSearchValue.split('');
1261-
1262-
// form regular expression
1263-
// let re = '.*';
1264-
// for (const ch of char_list) {
1265-
// re += ch + '.*';
1266-
// }
1267-
let re = '[';
1268-
for (const ch of char_list) {
1269-
re += ch;
1270-
}
1271-
re += ']';
1272-
1273-
const regex = new RegExp(re, 'g');
12741314
// console.log(regex);
12751315

12761316
// const str = 'Pythonmost_frequent';
@@ -1294,20 +1334,37 @@ export class CodeSnippetDisplay extends React.Component<
12941334
// TODO: filter codes nippet with regex!
12951335
// filter with search
12961336
const matchIndices: { [key: number]: number[] } = {};
1297-
let filteredSnippets = this.props.codeSnippets.filter(codeSnippet => {
1298-
const matchIndex = this.matchSnippet(
1299-
codeSnippet.id,
1300-
regex,
1301-
codeSnippet.language + codeSnippet.name,
1302-
char_list
1303-
);
1304-
if (matchIndex) {
1305-
matchIndices[matchIndex[0]] = matchIndex[1];
1337+
let filteredSnippets = this.props.codeSnippets;
1338+
if (searchValue !== '') {
1339+
// remove space
1340+
const tempSearchValue = searchValue.replace(/ /g, '');
1341+
const char_list = tempSearchValue.split('');
1342+
1343+
// form regular expression
1344+
let re = '';
1345+
for (const ch of char_list) {
1346+
re += '(' + ch + ').*';
13061347
}
1307-
return matchIndex;
1308-
});
1309-
console.log(filteredSnippets);
1310-
console.log(matchIndices);
1348+
re = re.substring(0, re.length - 2);
1349+
console.log('regex:' + re);
1350+
1351+
const regex = new RegExp(re, 'gi');
1352+
1353+
filteredSnippets = this.props.codeSnippets.filter(codeSnippet => {
1354+
const matchIndex = this.matchSnippet(
1355+
codeSnippet.id,
1356+
regex,
1357+
codeSnippet.language + codeSnippet.name,
1358+
char_list
1359+
);
1360+
console.log(matchIndex);
1361+
1362+
if (matchIndex) {
1363+
matchIndices[matchIndex[0]] = matchIndex[1];
1364+
}
1365+
return matchIndex !== null;
1366+
});
1367+
}
13111368

13121369
// filter with tags
13131370
if (filterTags.length !== 0) {
@@ -1321,12 +1378,21 @@ export class CodeSnippetDisplay extends React.Component<
13211378
});
13221379
}
13231380

1324-
this.setState({
1325-
codeSnippets: filteredSnippets,
1326-
matchIndices: matchIndices,
1327-
searchValue: searchValue,
1328-
filterTags: filterTags
1329-
});
1381+
console.log(filteredSnippets);
1382+
console.log(matchIndices);
1383+
1384+
this.setState(
1385+
{
1386+
codeSnippets: filteredSnippets,
1387+
matchIndices: matchIndices,
1388+
searchValue: searchValue,
1389+
filterTags: filterTags
1390+
},
1391+
() => {
1392+
console.log('snippets filtered');
1393+
}
1394+
);
1395+
console.log(this.state.codeSnippets);
13301396
};
13311397

13321398
getActiveTags(): string[] {

0 commit comments

Comments
 (0)