@ -3,6 +3,7 @@ import { createContext, useReducer } from 'react'
import {
findLinesInStringWithMatch ,
getDirectory ,
replaceAllInFile ,
replaceTextInLine
} from '../components/results/SearchHelper'
import { SearchReducer } from '../reducers/Reducer'
@ -11,7 +12,8 @@ import {
SearchResult ,
SearchResultLine ,
SearchResultLineLine ,
SearchingInitialState
SearchingInitialState ,
undoBufferRecord
} from '../types'
import { filePathFilter } from '@jsdevtools/file-path-filter'
import { escapeRegExp } from 'lodash'
@ -29,7 +31,7 @@ export interface SearchingStateInterface {
setSearchResults : ( value : SearchResult [ ] ) = > void
findText : ( path : string ) = > Promise < SearchResultLine [ ] >
hightLightInPath : ( result : SearchResult , line : SearchResultLineLine ) = > void
replaceText : ( result : SearchResult , line : SearchResultLineLine ) = > void
replaceText : ( result : SearchResult , line : SearchResultLineLine ) = > Promise < void >
reloadFile : ( file : string ) = > void
toggleCaseSensitive : ( ) = > void
toggleMatchWholeWord : ( ) = > void
@ -37,6 +39,9 @@ export interface SearchingStateInterface {
setReplaceWithoutConfirmation : ( value : boolean ) = > void
disableForceReload : ( file : string ) = > void
updateCount : ( count : number , file : string ) = > void
replaceAllInFile : ( result : SearchResult ) = > Promise < void >
undoReplace : ( buffer : undoBufferRecord ) = > Promise < void >
clearUndo : ( ) = > void
}
export const SearchContext = createContext < SearchingStateInterface > ( null )
@ -153,13 +158,7 @@ export const SearchProvider = ({
try {
if ( state . find . length < 1 ) return
const text = await plugin . call ( 'fileManager' , 'readFile' , path )
let flags = 'g'
let find = state . find
if ( ! state . casesensitive ) flags += 'i'
if ( ! state . useRegExp ) find = escapeRegExp ( find )
if ( state . matchWord ) find = ` \\ b ${ find } \\ b `
const re = new RegExp ( find , flags )
const result : SearchResultLine [ ] = findLinesInStringWithMatch ( text , re )
const result : SearchResultLine [ ] = findLinesInStringWithMatch ( text , createRegExFromFind ( ) )
return result
} catch ( e ) { }
} ,
@ -180,19 +179,73 @@ export const SearchProvider = ({
'readFile' ,
result . path
)
const replaced = replaceTextInLine ( content , line , state . replace )
await plugin . call (
'fileManager' ,
'setFile' ,
result . path ,
replaceTextInLine ( content , line , state . replace )
replaced
)
setUndoState ( content , replaced , result . path )
} catch ( e ) {
throw new Error ( e )
}
} ,
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
)
setUndoState ( content , replaced , result . path )
} ,
undoReplace : async ( buffer : undoBufferRecord ) = > {
const content = await plugin . call (
'fileManager' ,
'readFile' ,
buffer . path
)
if ( buffer . newContent !== content ) {
value . clearUndo ( )
throw new Error ( 'Can not undo replace, file has been changed.' )
}
await plugin . call (
'fileManager' ,
'setFile' ,
buffer . path ,
buffer . oldContent
)
await plugin . call (
'fileManager' ,
'open' ,
buffer . path
)
value . clearUndo ( )
} ,
clearUndo : ( ) = > {
dispatch ( {
type : 'CLEAR_UNDO' ,
payload : undefined
} )
}
}
const reloadStateForFile = async ( file : string ) = > {
await value . reloadFile ( file )
}
@ -200,6 +253,7 @@ export const SearchProvider = ({
useEffect ( ( ) = > {
plugin . on ( 'filePanel' , 'setWorkspace' , ( ) = > {
value . setSearchResults ( null )
value . clearUndo ( )
} )
plugin . on ( 'fileManager' , 'fileSaved' , async file = > {
await reloadStateForFile ( file )
@ -222,6 +276,30 @@ export const SearchProvider = ({
return results
}
const setUndoState = async ( oldContent : string , newContent : string , path : string ) = > {
const workspace = await plugin . call ( 'filePanel' , 'getCurrentWorkspace' )
const undo = {
oldContent ,
newContent ,
path ,
workspace
}
dispatch ( {
type : 'SET_UNDO' ,
payload : undo
} )
}
const createRegExFromFind = ( ) = > {
let flags = 'g'
let find = state . find
if ( ! state . casesensitive ) flags += 'i'
if ( ! state . useRegExp ) find = escapeRegExp ( find )
if ( state . matchWord ) find = ` \\ b ${ find } \\ b `
const re = new RegExp ( find , flags )
return re
}
useEffect ( ( ) = > {
if ( state . find ) {
( async ( ) = > {