diff --git a/apps/remix-ide-e2e/src/tests/search.test.ts b/apps/remix-ide-e2e/src/tests/search.test.ts index 19fe83da3c..9982747e03 100644 --- a/apps/remix-ide-e2e/src/tests/search.test.ts +++ b/apps/remix-ide-e2e/src/tests/search.test.ts @@ -67,6 +67,8 @@ module.exports = { }, 'Should replace text': function (browser: NightwatchBrowser) { browser + .waitForElementVisible('*[data-id="toggle_replace"]').click('*[data-id="toggle_replace"]') + .waitForElementVisible('*[id="search_replace"]') .setValue('*[id="search_replace"]', 'replacing').pause(1000) .waitForElementVisible('*[data-id="contracts/2_Owner.sol-30-71"]') .moveToElement('*[data-id="contracts/2_Owner.sol-30-71"]', 10, 10) diff --git a/apps/remix-ide/src/app/editor/editor.js b/apps/remix-ide/src/app/editor/editor.js index 875835d8ff..247adbf391 100644 --- a/apps/remix-ide/src/app/editor/editor.js +++ b/apps/remix-ide/src/app/editor/editor.js @@ -12,7 +12,7 @@ const profile = { name: 'editor', description: 'service - editor', version: packageJson.version, - methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addAnnotation', 'gotoLine', 'getCursorPosition'] + methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addAnnotation', 'gotoLine', 'revealRange', 'getCursorPosition'] } class Editor extends Plugin { @@ -390,6 +390,20 @@ class Editor extends Plugin { this.emit('revealLine', line + 1, col) } + /** + * Reveals the range in the editor. + * @param {number} startLineNumber + * @param {number} startColumn + * @param {number} endLineNumber + * @param {number} endColumn + */ + revealRange (startLineNumber, startColumn, endLineNumber, endColumn) { + if (!this.activated) return + this.emit('focus') + console.log(startLineNumber, startColumn, endLineNumber, endColumn) + this.emit('revealRange', startLineNumber, startColumn, endLineNumber, endColumn) + } + /** * Scrolls to a line. If center is true, it puts the line in middle of screen (or attempts to). * @param {number} line The line to scroll to diff --git a/apps/remix-ide/src/app/tabs/search.tsx b/apps/remix-ide/src/app/tabs/search.tsx index 6914ed0150..057653a8d8 100644 --- a/apps/remix-ide/src/app/tabs/search.tsx +++ b/apps/remix-ide/src/app/tabs/search.tsx @@ -4,7 +4,7 @@ import React from 'react' // eslint-disable-line import { SearchTab } from '@remix-ui/search' const profile = { name: 'search', - displayName: 'Search', + displayName: 'Search in files', methods: [''], events: [], icon: 'assets/img/Search_Icon.svg', diff --git a/libs/remix-ui/editor/src/lib/actions/editor.ts b/libs/remix-ui/editor/src/lib/actions/editor.ts index 0b49c0686b..b718ffca5a 100644 --- a/libs/remix-ui/editor/src/lib/actions/editor.ts +++ b/libs/remix-ui/editor/src/lib/actions/editor.ts @@ -1,3 +1,5 @@ +import { IRange } from "monaco-editor"; + export interface Action { type: string; payload: Record @@ -49,6 +51,27 @@ export const reducerActions = (models = initialState, action: Action) => { editor.setPosition({ column, lineNumber: line }) return models } + case 'REVEAL_RANGE': { + if (!editor) return models + const range: IRange = { + startLineNumber: action.payload.startLineNumber +1, + startColumn: action.payload.startColumn, + endLineNumber: action.payload.endLineNumber + 1, + endColumn: action.payload.endColumn + } + // reset to start of line + if(action.payload.startColumn < 100){ + editor.revealRange({ + startLineNumber: range.startLineNumber, + startColumn: 1, + endLineNumber: range.endLineNumber, + endColumn: 1 + }) + }else{ + editor.revealRangeInCenter(range) + } + return models + } case 'FOCUS': { if (!editor) return models editor.focus() @@ -106,6 +129,20 @@ export const reducerListener = (plugin, dispatch, monaco, editor, events) => { }) }) + plugin.on('editor', 'revealRange', (startLineNumber, startColumn, endLineNumber, endColumn) => { + dispatch({ + type: 'REVEAL_RANGE', + payload: { + startLineNumber, + startColumn, + endLineNumber, + endColumn + }, + monaco, + editor + }) + }) + plugin.on('editor', 'focus', () => { dispatch({ type: 'FOCUS', diff --git a/libs/remix-ui/search/src/lib/components/Exclude.tsx b/libs/remix-ui/search/src/lib/components/Exclude.tsx index 36d3bdd103..c334116a6c 100644 --- a/libs/remix-ui/search/src/lib/components/Exclude.tsx +++ b/libs/remix-ui/search/src/lib/components/Exclude.tsx @@ -17,8 +17,8 @@ export const Exclude = props => { return ( <> -
- +
+ { return ( <>
-
{ + const { setReplaceEnabled } = useContext(SearchContext) + const [expanded, setExpanded] = useState(false) + const toggleExpand = () => setExpanded(!expanded) + useEffect(() => { + setReplaceEnabled(expanded) + }, [expanded]) + return ( +
+
+
+ + {expanded ? : null} +
+
+ ) +} diff --git a/libs/remix-ui/search/src/lib/components/Include.tsx b/libs/remix-ui/search/src/lib/components/Include.tsx index ab50233885..bfd0a33596 100644 --- a/libs/remix-ui/search/src/lib/components/Include.tsx +++ b/libs/remix-ui/search/src/lib/components/Include.tsx @@ -13,8 +13,8 @@ export const Include = props => { return ( <> -
- +
+ { - const { setReplaceWithoutConfirmation } = useContext(SearchContext) + const { setReplaceWithoutConfirmation, state } = useContext(SearchContext) const change = e => { setReplaceWithoutConfirmation(e.target.checked) @@ -10,23 +10,25 @@ export const OverWriteCheck = props => { return ( <> -
-
- - + {state.replaceEnabled ? ( +
+
+ + +
-
+ ) : null} ) } diff --git a/libs/remix-ui/search/src/lib/components/Replace.tsx b/libs/remix-ui/search/src/lib/components/Replace.tsx index 7c39191e6d..7bbe7f80a9 100644 --- a/libs/remix-ui/search/src/lib/components/Replace.tsx +++ b/libs/remix-ui/search/src/lib/components/Replace.tsx @@ -12,7 +12,7 @@ export const Replace = props => { return ( <>
- + { @@ -16,8 +17,7 @@ return ( <>
- - + diff --git a/libs/remix-ui/search/src/lib/components/results/ResultItem.tsx b/libs/remix-ui/search/src/lib/components/results/ResultItem.tsx index 91bb40b51b..0728d220a1 100644 --- a/libs/remix-ui/search/src/lib/components/results/ResultItem.tsx +++ b/libs/remix-ui/search/src/lib/components/results/ResultItem.tsx @@ -86,12 +86,13 @@ export const ResultItem = (props: ResultItemProps) => { {!toggleExpander && !loading ? (
{lines.map((line, index) => ( + index < state.maxLines ? + />: null ))}
) : null} diff --git a/libs/remix-ui/search/src/lib/components/results/ResultSummary.tsx b/libs/remix-ui/search/src/lib/components/results/ResultSummary.tsx index 157aa43006..0d4a640a04 100644 --- a/libs/remix-ui/search/src/lib/components/results/ResultSummary.tsx +++ b/libs/remix-ui/search/src/lib/components/results/ResultSummary.tsx @@ -47,15 +47,16 @@ export const ResultSummary = (props: ResultSummaryProps) => { className='search_plugin_search_line pb-1' >
{lineItem.left.substring(lineItem.left.length - 20).trimStart()}
- {lineItem.center} - {state.replace? {state.replace}:<>} + {lineItem.center} + {state.replace && state.replaceEnabled? {state.replace}:<>}
{lineItem.right.substring(0, 100)}
+ {state.replaceEnabled?
{ replace(lineItem) }} className="codicon codicon-find-replace" role="button" aria-label="Replace" aria-disabled="false">
-
+
:null}
))} diff --git a/libs/remix-ui/search/src/lib/components/results/Results.tsx b/libs/remix-ui/search/src/lib/components/results/Results.tsx index b2094d23c9..66bee34149 100644 --- a/libs/remix-ui/search/src/lib/components/results/Results.tsx +++ b/libs/remix-ui/search/src/lib/components/results/Results.tsx @@ -5,13 +5,13 @@ import { ResultItem } from './ResultItem' export const Results = () => { const { state } = useContext(SearchContext) return ( -
+
{state.find ?
{state.count} results
: null} - {state.count < state.maxResults && state.searchResults && + {state.find && state.count >= state.maxResults?
The result set only contains a subset of all matches

Please narrow down your search.
: null} + {state.searchResults && state.searchResults.map((result, index) => { - return + return index : null })} - {state.find && state.count >= state.maxResults?
Too many results to display.

Please narrow your search.
: null}
) } diff --git a/libs/remix-ui/search/src/lib/context/context.tsx b/libs/remix-ui/search/src/lib/context/context.tsx index bbc3c72795..267fa2a92e 100644 --- a/libs/remix-ui/search/src/lib/context/context.tsx +++ b/libs/remix-ui/search/src/lib/context/context.tsx @@ -20,6 +20,7 @@ export interface SearchingStateInterface { state: SearchState setFind: (value: string) => void setReplace: (value: string) => void + setReplaceEnabled: (value: boolean) => void setInclude: (value: string) => void setExclude: (value: string) => void setCaseSensitive: (value: boolean) => void @@ -63,6 +64,12 @@ export const SearchProvider = ({ payload: value }) }, + setReplaceEnabled: (value: boolean) => { + dispatch({ + type: 'SET_REPLACE_ENABLED', + payload: value + }) + }, setInclude: (value: string) => { dispatch({ type: 'SET_INCLUDE', @@ -144,7 +151,7 @@ export const SearchProvider = ({ findText: async (path: string) => { if (!plugin) return try { - if (state.find.length < 3) return + if (state.find.length < 1) return const text = await plugin.call('fileManager', 'readFile', path) let flags = 'g' let find = state.find @@ -162,6 +169,7 @@ export const SearchProvider = ({ ) => { await plugin.call('editor', 'discardHighlight') await plugin.call('editor', 'highlight', line.position, result.path) + await plugin.call('editor', 'revealRange', line.position.start.line, line.position.start.column, line.position.end.line, line.position.end.column) }, replaceText: async (result: SearchResult, line: SearchResultLineLine) => { try { diff --git a/libs/remix-ui/search/src/lib/reducers/Reducer.ts b/libs/remix-ui/search/src/lib/reducers/Reducer.ts index 05e9efaecb..47b9cef21f 100644 --- a/libs/remix-ui/search/src/lib/reducers/Reducer.ts +++ b/libs/remix-ui/search/src/lib/reducers/Reducer.ts @@ -15,6 +15,12 @@ export const SearchReducer = (state: SearchState = SearchingInitialState, action replace: action.payload, } + case 'SET_REPLACE_ENABLED': + return { + ...state, + replaceEnabled: action.payload, + } + case 'SET_INCLUDE': return { ...state, diff --git a/libs/remix-ui/search/src/lib/search.css b/libs/remix-ui/search/src/lib/search.css index 895ce83e7f..8774dc310c 100644 --- a/libs/remix-ui/search/src/lib/search.css +++ b/libs/remix-ui/search/src/lib/search.css @@ -103,4 +103,21 @@ .search_plugin_search_tab .search_plugin_result_count_number { font-size: x-small; +} + +.search_plugin_find_container { + display: flex; + flex-direction: row; +} + +.search_plugin_find_container_internal { + display: flex; + flex-direction: column; + flex-grow: 1; +} + +.search_plugin_find_container_arrow { + display: flex !important; + align-items: center; + cursor: pointer !important; } \ No newline at end of file diff --git a/libs/remix-ui/search/src/lib/types/index.ts b/libs/remix-ui/search/src/lib/types/index.ts index af76487c51..05f2200b1d 100644 --- a/libs/remix-ui/search/src/lib/types/index.ts +++ b/libs/remix-ui/search/src/lib/types/index.ts @@ -39,6 +39,7 @@ export interface SearchState { find: string, searchResults: SearchResult[], replace: string, + replaceEnabled: boolean, include: string, exclude: string, casesensitive: boolean, @@ -48,6 +49,8 @@ export interface SearchState { timeStamp: number, count: number, maxResults: number + maxFiles: number, + maxLines: number } export const SearchingInitialState: SearchState = { @@ -55,6 +58,7 @@ export const SearchingInitialState: SearchState = { replace: '', include: '', exclude: '', + replaceEnabled: false, searchResults: [], casesensitive: false, matchWord: false, @@ -62,5 +66,7 @@ export const SearchingInitialState: SearchState = { replaceWithOutConfirmation: false, timeStamp: 0, count: 0, - maxResults: 500 + maxResults: 1500, + maxFiles: 100, + maxLines: 200 } \ No newline at end of file