- {state.find ?
showing {state.count} results {state.fileCount} in files
: null}
- {state.find && state.clipped?
The result set only shows a subset of all matches
Please narrow down your search.
: null}
+
+
+ {' '}
+ {state.searching && !state.clipped
+ ? `searching in ${state.searching}`
+ : null}
+
+ {state.find && !state.clipped ? (
+
+ showing {state.count} results {state.fileCount} in files
+
+ ) : null}
+ {state.find && state.clipped ? (
+
+ Too many resuls to display...
Please narrow down your search.
+
+ ) : null}
{state.searchResults &&
state.searchResults.map((result, index) => {
- return index
: null
+ return
})}
)
diff --git a/libs/remix-ui/search/src/lib/context/context.tsx b/libs/remix-ui/search/src/lib/context/context.tsx
index 6d270ba1b2..a8d3a7fab0 100644
--- a/libs/remix-ui/search/src/lib/context/context.tsx
+++ b/libs/remix-ui/search/src/lib/context/context.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useRef } from 'react'
+import React, { useEffect, useRef, useState } from 'react'
import { createContext, useReducer } from 'react'
import {
findLinesInStringWithMatch,
@@ -31,7 +31,10 @@ export interface SearchingStateInterface {
setSearchResults: (value: SearchResult[]) => void
findText: (path: string) => Promise
hightLightInPath: (result: SearchResult, line: SearchResultLineLine) => void
- replaceText: (result: SearchResult, line: SearchResultLineLine) => Promise
+ replaceText: (
+ result: SearchResult,
+ line: SearchResultLineLine
+ ) => Promise
reloadFile: (file: string) => void
toggleCaseSensitive: () => void
toggleMatchWholeWord: () => void
@@ -39,9 +42,10 @@ export interface SearchingStateInterface {
setReplaceWithoutConfirmation: (value: boolean) => void
disableForceReload: (file: string) => void
updateCount: (count: number, file: string) => void
- replaceAllInFile: (result: SearchResult) => Promise
+ replaceAllInFile: (result: SearchResult) => Promise
undoReplace: (buffer: undoBufferRecord) => Promise
clearUndo: () => void
+ cancelSearch: () => Promise
}
export const SearchContext = createContext(null)
@@ -53,11 +57,12 @@ export const SearchProvider = ({
plugin = undefined
} = {}) => {
const [state, dispatch] = useReducer(reducer, initialState)
-
- const reloadTimeOut = useRef(null)
+ const [files, setFiles] = useState([])
+ const clearSearchingTimeout = useRef(null)
const value = {
state,
setFind: (value: string) => {
+ plugin.cancel('fileManager')
dispatch({
type: 'SET_FIND',
payload: value
@@ -165,14 +170,30 @@ export const SearchProvider = ({
payload: { count, file }
})
},
+ setSearching(file: string) {
+ dispatch({
+ type: 'SET_SEARCHING',
+ payload: file
+ })
+ },
+
findText: async (path: string) => {
if (!plugin) return
try {
if (state.find.length < 1) return
+ value.setSearching(path)
const text = await plugin.call('fileManager', 'readFile', path)
- const result: SearchResultLine[] = findLinesInStringWithMatch(text, createRegExFromFind())
+ const result: SearchResultLine[] = findLinesInStringWithMatch(
+ text,
+ createRegExFromFind()
+ )
+ clearTimeout(clearSearchingTimeout.current)
+ clearSearchingTimeout.current = setTimeout(() => value.setSearching(null), 500)
return result
- } catch (e) { }
+ } catch (e) {
+ value.setSearching(null)
+ // do nothing
+ }
},
hightLightInPath: async (
result: SearchResult,
@@ -180,7 +201,14 @@ 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)
+ 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 {
@@ -192,12 +220,7 @@ export const SearchProvider = ({
result.path
)
const replaced = replaceTextInLine(content, line, state.replace)
- await plugin.call(
- 'fileManager',
- 'setFile',
- result.path,
- replaced
- )
+ await plugin.call('fileManager', 'setFile', result.path, replaced)
setUndoState(content, replaced, result.path)
} catch (e) {
throw new Error(e)
@@ -205,26 +228,17 @@ export const SearchProvider = ({
},
replaceAllInFile: async (result: SearchResult) => {
await plugin.call('editor', 'discardHighlight')
- const content = await plugin.call(
- 'fileManager',
- 'readFile',
- result.path
- )
- const replaced = replaceAllInFile(content, createRegExFromFind(), state.replace)
- await plugin.call(
- 'fileManager',
- 'setFile',
- result.path,
- replaced
- )
- await plugin.call(
- 'fileManager',
- 'open',
- result.path
+ const content = await plugin.call('fileManager', 'readFile', result.path)
+ const replaced = replaceAllInFile(
+ content,
+ createRegExFromFind(),
+ state.replace
)
+ await plugin.call('fileManager', 'setFile', result.path, replaced)
+ await plugin.call('fileManager', 'open', result.path)
setUndoState(content, replaced, result.path)
},
- setUndoEnabled: (path:string, workspace: string, content: string) => {
+ setUndoEnabled: (path: string, workspace: string, content: string) => {
dispatch({
type: 'SET_UNDO_ENABLED',
payload: {
@@ -235,11 +249,7 @@ export const SearchProvider = ({
})
},
undoReplace: async (buffer: undoBufferRecord) => {
- const content = await plugin.call(
- 'fileManager',
- 'readFile',
- buffer.path
- )
+ const content = await plugin.call('fileManager', 'readFile', buffer.path)
if (buffer.newContent !== content) {
throw new Error('Can not undo replace, file has been changed.')
}
@@ -249,41 +259,58 @@ export const SearchProvider = ({
buffer.path,
buffer.oldContent
)
- await plugin.call(
- 'fileManager',
- 'open',
- buffer.path
- )
+ await plugin.call('fileManager', 'open', buffer.path)
},
clearUndo: () => {
- dispatch ({
+ dispatch({
type: 'CLEAR_UNDO',
payload: undefined
})
- }
- }
+ },
+ clearStats: () => {
+ dispatch({
+ type: 'CLEAR_STATS',
+ payload: undefined
+ })
+ },
+
+ cancelSearch: async () => {
+ plugin.cancel('fileManager')
+ value.clearStats()
+ },
+ setClipped: (value: boolean) => {
+ dispatch({
+ type: 'SET_CLIPPED',
+ payload: value
+ })
+ }
+ }
const reloadStateForFile = async (file: string) => {
await value.reloadFile(file)
}
useEffect(() => {
- plugin.on('filePanel', 'setWorkspace', async (workspace) => {
+ plugin.on('filePanel', 'setWorkspace', async workspace => {
value.setSearchResults(null)
value.clearUndo()
value.setCurrentWorkspace(workspace.name)
+ setFiles(await getDirectory('/', plugin))
})
plugin.on('fileManager', 'fileSaved', async file => {
await reloadStateForFile(file)
await checkUndoState(file)
})
+ plugin.on('fileManager', 'fileAdded', async file => {
+ setFiles(await getDirectory('/', plugin))
+ })
plugin.on('fileManager', 'currentFileChanged', async file => {
value.setCurrentFile(file)
await checkUndoState(file)
})
-
+
return () => {
plugin.off('fileManager', 'fileChanged')
plugin.off('filePanel', 'setWorkspace')
@@ -296,7 +323,8 @@ export const SearchProvider = ({
paths.split(',').forEach(path => {
path = path.trim()
if (path.startsWith('*.')) path = path.replace(/(\*\.)/g, '**/*.')
- if (path.endsWith('/*') && !path.endsWith('/**/*')) path = path.replace(/(\*)/g, '**/*.*')
+ if (path.endsWith('/*') && !path.endsWith('/**/*'))
+ path = path.replace(/(\*)/g, '**/*.*')
results.push(path)
})
return results
@@ -305,19 +333,19 @@ export const SearchProvider = ({
const checkUndoState = async (path: string) => {
if (!plugin) return
try {
- const content = await plugin.call(
- 'fileManager',
- 'readFile',
- path
- )
+ const content = await plugin.call('fileManager', 'readFile', path)
const workspace = await plugin.call('filePanel', 'getCurrentWorkspace')
value.setUndoEnabled(path, workspace.name, content)
- } catch (e) {
+ } catch (e) {
console.log(e)
}
}
- const setUndoState = async (oldContent: string, newContent: string, path: string) => {
+ const setUndoState = async (
+ oldContent: string,
+ newContent: string,
+ path: string
+ ) => {
const workspace = await plugin.call('filePanel', 'getCurrentWorkspace')
const undo = {
oldContent,
@@ -341,29 +369,41 @@ export const SearchProvider = ({
return re
}
+ useEffect(() => {
+ if(state.count>500) {
+ value.setClipped(true)
+ value.cancelSearch()
+ }
+ }, [state.count])
+
useEffect(() => {
if (state.find) {
(async () => {
- const files = await getDirectory('/', plugin)
- const pathFilter: any = {}
- if (state.include) {
- pathFilter.include = setGlobalExpression(state.include)
- }
- if (state.exclude) {
- pathFilter.exclude = setGlobalExpression(state.exclude)
- }
- const filteredFiles = files.filter(filePathFilter(pathFilter)).map(file => {
- const r: SearchResult = {
- filename: file,
- lines: [],
- path: file,
- timeStamp: Date.now(),
- forceReload: false,
- count: 0
+ try {
+ const pathFilter: any = {}
+ if (state.include) {
+ pathFilter.include = setGlobalExpression(state.include)
+ }
+ if (state.exclude) {
+ pathFilter.exclude = setGlobalExpression(state.exclude)
}
- return r
- })
- value.setSearchResults(filteredFiles)
+ const filteredFiles = files
+ .filter(filePathFilter(pathFilter))
+ .map(file => {
+ const r: SearchResult = {
+ filename: file,
+ lines: [],
+ path: file,
+ timeStamp: Date.now(),
+ forceReload: false,
+ count: 0
+ }
+ return r
+ })
+ value.setSearchResults(filteredFiles)
+ } catch (e) {
+ console.log(e)
+ }
})()
}
}, [state.timeStamp])
diff --git a/libs/remix-ui/search/src/lib/reducers/Reducer.ts b/libs/remix-ui/search/src/lib/reducers/Reducer.ts
index 3e188f61fb..1455dab61e 100644
--- a/libs/remix-ui/search/src/lib/reducers/Reducer.ts
+++ b/libs/remix-ui/search/src/lib/reducers/Reducer.ts
@@ -5,6 +5,7 @@ export const SearchReducer = (state: SearchState = SearchingInitialState, action
case 'SET_FIND':
return {
...state,
+ searchResults: null,
find: action.payload,
timeStamp: Date.now()
}
@@ -64,6 +65,21 @@ export const SearchReducer = (state: SearchState = SearchingInitialState, action
...state,
}
}
+ case 'CLEAR_STATS':
+ return {
+ ...state,
+ count: 0,
+ fileCount: 0,
+ searchResults: null,
+ searching: null
+ }
+
+ case 'SET_SEARCHING':
+ return {
+ ...state,
+ searching: action.payload,
+ }
+
case 'CLEAR_UNDO': {
state.undoBuffer = []
return {
@@ -81,12 +97,7 @@ export const SearchReducer = (state: SearchState = SearchingInitialState, action
}
state.searchResults.forEach(file => {
if (file.count) {
- if(file.count > state.maxLines) {
- clipped = true
- count += state.maxLines
- }else{
- count += file.count
- }
+ count += file.count
fileCount++
}
})
@@ -99,6 +110,13 @@ export const SearchReducer = (state: SearchState = SearchingInitialState, action
} else {
return state
}
+
+ case 'SET_CLIPPED':
+ return {
+ ...state,
+ clipped: action.payload
+ }
+
case 'TOGGLE_CASE_SENSITIVE':
return {
...state,
diff --git a/libs/remix-ui/search/src/lib/search.css b/libs/remix-ui/search/src/lib/search.css
index acc789d51c..6e4a21ef89 100644
--- a/libs/remix-ui/search/src/lib/search.css
+++ b/libs/remix-ui/search/src/lib/search.css
@@ -133,4 +133,9 @@
white-space: pre;
text-overflow: ellipsis;
overflow: hidden;
+}
+.search_plugin_search_indicator{
+ white-space: pre;
+ text-overflow: ellipsis;
+ overflow: hidden;
}
\ 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 231c4ebf93..3e32c6a974 100644
--- a/libs/remix-ui/search/src/lib/types/index.ts
+++ b/libs/remix-ui/search/src/lib/types/index.ts
@@ -63,7 +63,8 @@ export interface SearchState {
clipped: boolean,
undoBuffer: Record[],
currentFile: string,
- workspace: string
+ workspace: string,
+ searching: string | null,
}
export const SearchingInitialState: SearchState = {
@@ -85,5 +86,6 @@ export const SearchingInitialState: SearchState = {
clipped: false,
undoBuffer: null,
currentFile: '',
- workspace: ''
+ workspace: '',
+ searching: null
}
\ No newline at end of file