Commit 821d4507 authored by tom's avatar tom

highlight search term in result list

parent a6096618
......@@ -8,6 +8,11 @@ import type { File, Monaco } from './types';
import CodeEditorSideBar from './CodeEditorSideBar';
import * as themes from './utils/themes';
const EDITOR_OPTIONS = {
readOnly: true,
minimap: { enabled: false },
};
interface Props {
data: Array<File>;
}
......@@ -30,6 +35,10 @@ const CodeEditor = ({ data }: Props) => {
monaco.editor.defineTheme('blockscout-light', themes.light);
monaco.editor.defineTheme('blockscout-dark', themes.dark);
monaco.editor.setTheme(colorMode === 'light' ? 'blockscout-light' : 'blockscout-dark');
data.slice(1).forEach((file) => {
monaco.editor.createModel(file.source_code, 'sol', monaco.Uri.parse(file.file_path));
});
// componentDidMount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ ]);
......@@ -37,7 +46,9 @@ const CodeEditor = ({ data }: Props) => {
const handleSelectFile = React.useCallback((index: number, lineNumber?: number) => {
setIndex(index);
if (lineNumber !== undefined && !Object.is(lineNumber, NaN)) {
editorRef.current?.revealLineInCenter(lineNumber);
window.setTimeout(() => {
editorRef.current?.revealLineInCenter(lineNumber);
}, 0);
}
}, []);
......@@ -48,7 +59,7 @@ const CodeEditor = ({ data }: Props) => {
language="sol"
path={ data[index].file_path }
defaultValue={ data[index].source_code }
options={{ readOnly: true, inlayHints: { enabled: 'off' }, minimap: { enabled: false } }}
options={ EDITOR_OPTIONS }
onMount={ handleEditorDidMount }
/>
</Box>
......
import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Input } from '@chakra-ui/react';
import { Accordion, Box, Input } from '@chakra-ui/react';
import React from 'react';
import type { File, Monaco, SearchResult } from './types';
import useDebounce from 'lib/hooks/useDebounce';
import CodeEditorSearchResultItem from './CodeEditorSearchResultItem';
import CodeEditorSearchSection from './CodeEditorSearchSection';
interface Props {
data: Array<File>;
......@@ -45,11 +45,8 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect }: Props) => {
changeSearchTerm(event.target.value);
}, []);
const handleFileLineClick = React.useCallback((event: React.MouseEvent) => {
const filePath = (event.currentTarget as HTMLDivElement).getAttribute('data-file-path');
const lineNumber = (event.currentTarget as HTMLDivElement).getAttribute('data-line-number');
const handleResultItemClick = React.useCallback((filePath: string, lineNumber: number) => {
const fileIndex = data.findIndex((item) => item.file_path === filePath);
if (fileIndex > -1) {
onFileSelect(fileIndex, Number(lineNumber));
}
......@@ -65,30 +62,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect }: Props) => {
reduceMotion
mt={ 3 }
>
{
searchResults.map((item, index) => {
const fileName = item.file_path.split('/').at(-1);
return (
<AccordionItem key={ index } borderWidth="0px" _last={{ borderBottomWidth: '0px' }}>
<AccordionButton p={ 0 } _hover={{ bgColor: 'inherit' }} fontSize="sm">
<AccordionIcon/>
<span>{ fileName }</span>
</AccordionButton>
<AccordionPanel p={ 0 }>
{ item.matches.map((match) => (
<CodeEditorSearchResultItem
key={ item.file_path + '_' + match.startLineNumber + '_' + match.startColumn }
filePath={ item.file_path }
onClick={ handleFileLineClick }
{ ...match }
/>
),
) }
</AccordionPanel>
</AccordionItem>
);
})
}
{ searchResults.map((item) => <CodeEditorSearchSection key={ item.file_path } data={ item } onItemClick={ handleResultItemClick }/>) }
</Accordion>
</Box>
);
......
import { Box } from '@chakra-ui/react';
import { Box, chakra } from '@chakra-ui/react';
import React from 'react';
import type { SearchResult } from './types';
......@@ -9,7 +9,25 @@ interface Props extends ArrayElement<SearchResult['matches']> {
onClick: (event: React.MouseEvent) => void;
}
const CodeEditorSearchResultItem = ({ lineContent, filePath, onClick, startLineNumber }: Props) => {
const calculateStartPosition = (lineContent: string, startColumn: number) => {
let start = 0;
for (let index = 0; index < startColumn; index++) {
const element = lineContent[index];
if (element === ' ') {
start = index + 1;
continue;
}
}
return start ? start - 1 : 0;
};
const CodeEditorSearchResultItem = ({ lineContent, filePath, onClick, startLineNumber, startColumn, endColumn }: Props) => {
const start = calculateStartPosition(lineContent, startColumn);
return (
<Box
whiteSpace="nowrap"
......@@ -20,7 +38,9 @@ const CodeEditorSearchResultItem = ({ lineContent, filePath, onClick, startLineN
data-line-number={ startLineNumber }
onClick={ onClick }
>
{ lineContent }
<span>{ lineContent.slice(start, startColumn - 1) }</span>
<chakra.span bgColor="lime">{ lineContent.slice(startColumn - 1, endColumn - 1) }</chakra.span>
<span>{ lineContent.slice(endColumn - 1) }</span>
</Box>
);
};
......
import { AccordionButton, AccordionItem, AccordionIcon, AccordionPanel } from '@chakra-ui/react';
import React from 'react';
import type { SearchResult } from './types';
import CodeEditorSearchResultItem from './CodeEditorSearchResultItem';
interface Props {
data: SearchResult;
onItemClick: (filePath: string, lineNumber: number) => void;
}
const CodeEditorSearchSection = ({ data, onItemClick }: Props) => {
const fileName = data.file_path.split('/').at(-1);
const handleFileLineClick = React.useCallback((event: React.MouseEvent) => {
const lineNumber = Number((event.currentTarget as HTMLDivElement).getAttribute('data-line-number'));
if (!Object.is(lineNumber, NaN)) {
onItemClick(data.file_path, Number(lineNumber));
}
}, [ data.file_path, onItemClick ]);
return (
<AccordionItem borderWidth="0px" _last={{ borderBottomWidth: '0px' }}>
<AccordionButton p={ 0 } _hover={{ bgColor: 'inherit' }} fontSize="sm">
<AccordionIcon/>
<span>{ fileName }</span>
</AccordionButton>
<AccordionPanel p={ 0 }>
{ data.matches.map((match) => (
<CodeEditorSearchResultItem
key={ data.file_path + '_' + match.startLineNumber + '_' + match.startColumn }
filePath={ data.file_path }
onClick={ handleFileLineClick }
{ ...match }
/>
),
) }
</AccordionPanel>
</AccordionItem>
);
};
export default React.memo(CodeEditorSearchSection);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment