Added "Buffer Only Mode" to Global Search & Replace (#545).

emscripten build is now multi-threaded only.
This commit is contained in:
Martín Lucas Golini
2025-07-05 20:57:21 -03:00
parent 79966343ba
commit 4877a4341a
24 changed files with 305 additions and 396 deletions

View File

@@ -160,7 +160,6 @@ newoption { trigger = "with-gles2", description = "Compile with GLES2 support" }
newoption { trigger = "with-gles1", description = "Compile with GLES1 support" }
newoption { trigger = "without-mojoal", description = "Compile without mojoAL as OpenAL implementation (that requires SDL2 backend). Instead it will use openal-soft." }
newoption { trigger = "use-frameworks", description = "In macOS it will try to link the external libraries from its frameworks. For example, instead of linking against SDL2 it will link agains SDL2.framework." }
newoption { trigger = "with-emscripten-pthreads", description = "Enables emscripten build to use posix threads" }
newoption { trigger = "with-mold-linker", description = "Tries to use the mold linker instead of the default linker of the toolchain" }
newoption { trigger = "with-debug-symbols", description = "Release builds are built with debug symbols." }
newoption { trigger = "thread-sanitizer", description ="Compile with ThreadSanitizer." }
@@ -396,9 +395,7 @@ function build_base_configuration( package_name )
configuration "emscripten"
buildoptions { "-s USE_SDL=2" }
if _OPTIONS["with-emscripten-pthreads"] then
buildoptions { "-s USE_PTHREADS=1" }
end
buildoptions { "-s USE_PTHREADS=1" }
end
function build_base_cpp_configuration( package_name )
@@ -447,9 +444,7 @@ function build_base_cpp_configuration( package_name )
configuration "emscripten"
buildoptions { "-s USE_SDL=2" }
if _OPTIONS["with-emscripten-pthreads"] then
buildoptions { "-s USE_PTHREADS=1" }
end
buildoptions { "-s USE_PTHREADS=1" }
end
function add_cross_config_links()
@@ -610,10 +605,8 @@ function build_link_configuration( package_name, use_ee_icon )
if os.is_real("emscripten") then
linkoptions{ "--profiling --profiling-funcs -s DEMANGLE_SUPPORT=1 -s NO_DISABLE_EXCEPTION_CATCHING -sALLOW_MEMORY_GROWTH=1" }
if _OPTIONS["with-emscripten-pthreads"] then
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }
end
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }
end
fix_shared_lib_linking_path( package_name, "libeepp-debug" )
@@ -645,11 +638,8 @@ function build_link_configuration( package_name, use_ee_icon )
configuration "emscripten"
linkoptions { "-s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2" }
buildoptions { "-s USE_SDL=2" }
if _OPTIONS["with-emscripten-pthreads"] then
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }
end
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }
if _OPTIONS["with-gles1"] and ( not _OPTIONS["with-gles2"] or _OPTIONS["force-gles1"] ) then
linkoptions{ "-s LEGACY_GL_EMULATION=1" }

View File

@@ -12,7 +12,6 @@ newoption { trigger = "without-mojoal", description = "Compile without mojoAL as
newoption { trigger = "use-frameworks", description = "In macOS it will try to link the external libraries from its frameworks. For example, instead of linking against SDL2 it will link against SDL2.framework." }
newoption { trigger = "windows-vc-build", description = "This is used to build the framework in Visual Studio downloading its external dependencies and making them available to the VS project without having to install them manually." }
newoption { trigger = "windows-mingw-build", description = "This is used to build the framework with mingw downloading its external dependencies." }
newoption { trigger = "with-emscripten-pthreads", description = "Enables emscripten build to use posix threads" }
newoption { trigger = "with-mold-linker", description = "Tries to use the mold linker instead of the default linker of the toolchain" }
newoption { trigger = "with-debug-symbols", description = "Release builds are built with debug symbols." }
newoption { trigger = "thread-sanitizer", description = "Compile with ThreadSanitizer." }
@@ -269,9 +268,7 @@ function build_base_configuration( package_name )
filter "system:emscripten"
buildoptions { "-O3 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=worker,web" }
if _OPTIONS["with-emscripten-pthreads"] then
buildoptions { "-s USE_PTHREADS=1" }
end
buildoptions { "-s USE_PTHREADS=1" }
filter {}
end
@@ -311,9 +308,7 @@ function build_base_cpp_configuration( package_name )
filter "system:emscripten"
buildoptions { "-O3 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=worker,web" }
if _OPTIONS["with-emscripten-pthreads"] then
buildoptions { "-s USE_PTHREADS=1" }
end
buildoptions { "-s USE_PTHREADS=1" }
filter {}
end
@@ -464,11 +459,8 @@ function build_link_configuration( package_name, use_ee_icon )
targetname ( package_name .. extension )
linkoptions { "-O3 -s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2" }
buildoptions { "-O3 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=worker,web" }
if _OPTIONS["with-emscripten-pthreads"] then
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }
end
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }
if _OPTIONS["with-gles1"] and ( not _OPTIONS["with-gles2"] or _OPTIONS["force-gles1"] ) then
linkoptions{ "-s LEGACY_GL_EMULATION=1" }

View File

@@ -1,17 +0,0 @@
#!/bin/sh
# Currently latest emsdk tested and working version: latest-fastcomp
# remember to first set the environment
# source /path/to/emsdk/emsdk_env.sh
cd $(dirname "$0") || exit
unset CPLUS_INCLUDE_PATH
premake4 --file=../../premake4.lua --with-emscripten-pthreads --with-gles2 --with-static-eepp --platform=emscripten --with-backend=SDL2 gmake
cd ../../make/emscripten/ || exit
rm -rf ./assets
cp -r ../../bin/assets/ .
rm assets/fonts/NotoColorEmoji.ttf assets/fonts/DejaVuSansMonoNerdFontComplete.ttf assets/fonts/DroidSansFallbackFull.ttf
rm -rf ./ecode
mkdir ecode
cp -r ../../bin/assets/ ecode/assets/
rm ecode/assets/fonts/DejaVuSansMonoNerdFontComplete.ttf ecode/assets/fonts/DroidSansFallbackFull.ttf ecode/assets/fonts/NotoColorEmoji.ttf ecode/assets/test.zip ecode/assets/ca-bundle.pem ecode/assets/icon/ee.icns ecode/assets/icon/ee.rc ecode/assets/icon/ee.res ecode/assets/icon/ee.ico ecode/assets/fonts/*.png ecode/assets/fonts/*.fnt ecode/assets/fonts/OpenSans-Regular.ttf ecode/assets/icon/ecode.icns ecode/assets/icon/eterm* ecode/assets/icon/*.svg
rm -r ecode/assets/atlases ecode/assets/screenshots ecode/assets/cursors ecode/assets/layouts ecode/assets/maps ecode/assets/sounds ecode/assets/sprites ecode/assets/tiles ecode/assets/shaders ecode/assets/ui/uitheme*
emmake make -j"$(nproc)" "$@"

View File

@@ -385,7 +385,6 @@ bool UICodeEditorSplitter::loadFileFromPath( const std::string& path, UICodeEdit
void UICodeEditorSplitter::loadAsyncFileFromPath(
const std::string& path, UICodeEditor* codeEditor,
std::function<void( UICodeEditor* codeEditor, const std::string& path )> onLoaded ) {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
if ( !mThreadPool ) {
Log::error( "UICodeEditorSplitter::loadAsyncFileFromPath loading file async "
"without thread pool." );
@@ -417,15 +416,6 @@ void UICodeEditorSplitter::loadAsyncFileFromPath(
onLoaded( codeEditor, path );
} );
}
#else
loadFileFromPath( path, codeEditor );
if ( nullptr == codeEditor )
codeEditor = mCurEditor;
if ( nullptr == codeEditor && !mTabWidgets.empty() )
codeEditor = createCodeEditorInTabWidget( mTabWidgets[0] ).second;
if ( onLoaded )
onLoaded( codeEditor, path );
#endif
}
std::pair<UITab*, UICodeEditor*>

View File

@@ -208,6 +208,8 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
globalSearchBarConfig.wholeWord = ini.getValueB( "global_search_bar", "whole_word", false );
globalSearchBarConfig.escapeSequence =
ini.getValueB( "global_search_bar", "escape_sequence", false );
globalSearchBarConfig.bufferOnlyMode =
ini.getValueB( "global_search_bar", "buffer_only_mode", false );
term.shell = ini.getValue( "terminal", "shell" );
term.fontSize = ini.getValue( "terminal", "font_size", "11dp" );
@@ -362,6 +364,7 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
ini.setValueB( "global_search_bar", "regex", globalSearchBarConfig.regex );
ini.setValueB( "global_search_bar", "whole_word", globalSearchBarConfig.wholeWord );
ini.setValueB( "global_search_bar", "escape_sequence", globalSearchBarConfig.escapeSequence );
ini.setValueB( "global_search_bar", "buffer_only_mode", globalSearchBarConfig.bufferOnlyMode );
ini.setValue( "terminal", "shell", term.shell );
ini.setValue( "terminal", "font_size", term.fontSize.toString() );

View File

@@ -124,6 +124,7 @@ struct GlobalSearchBarConfig {
bool luaPattern{ false };
bool wholeWord{ false };
bool escapeSequence{ false };
bool bufferOnlyMode{ false };
};
struct ProjectDocumentConfig {

View File

@@ -614,6 +614,7 @@ R"html(
<CheckBox id="lua_pattern" text='@string(lua_pattern, "Lua Pattern")' selected="false" margin-right="8dp" />
<CheckBox id="escape_sequence" text='@string(use_escape_sequences, "Use escape sequences")' margin-right="8dp" selected="false"
tooltip='@string(escape_sequence_tooltip, "Replace \\, \t, \n, \r and \uXXXX (Unicode characters) with the corresponding control")' />
<CheckBox id="buffer_only_mode" text="@string(buffer_only_mode, Buffer Only Mode)" selected="false" tooltip="@string(buffer_only_mode_tooltip, Apply replacements to file buffers only.&#10;Changes won't be saved to disk until you explicitly save the files.)" visible="false" />
</StackLayout>
<hbox lw="mp" lh="wc">
<TextView text='@string(history, "History:")' margin-right="4dp" lh="18dp" focusable="false" />

View File

@@ -241,24 +241,28 @@ void App::updateEditorTabTitle( UICodeEditor* editor ) {
return;
if ( editor->getData() ) {
UITab* tab = (UITab*)editor->getData();
auto doc = editor->getDocumentRef();
std::string fileName( doc->getFilename() );
tab->ensureMainThread( [editor, isUniqueTabTitle, getTabWithSameTitle, getUniqueNameForTabs,
tab] {
auto doc = editor->getDocumentRef();
std::string fileName( doc->getFilename() );
if ( fileName != doc->getDefaultFileName() && !isUniqueTabTitle( tab ) ) {
auto tabsTitles = getUniqueNameForTabs( getTabWithSameTitle( tab ) );
for ( auto [ntab, title] : tabsTitles ) {
ntab->setText( title );
if ( ntab->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) )
ntab->getOwnedWidget()->asType<UICodeEditor>()->addClass( NOT_UNIQUE_FILENAME );
if ( fileName != doc->getDefaultFileName() && !isUniqueTabTitle( tab ) ) {
auto tabsTitles = getUniqueNameForTabs( getTabWithSameTitle( tab ) );
for ( auto [ntab, title] : tabsTitles ) {
ntab->setText( title );
if ( ntab->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) )
ntab->getOwnedWidget()->asType<UICodeEditor>()->addClass(
NOT_UNIQUE_FILENAME );
}
} else if ( tab->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ) {
tab->getOwnedWidget()->asType<UICodeEditor>()->removeClass( NOT_UNIQUE_FILENAME );
tab->setText( fileName );
}
} else if ( tab->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ) {
tab->getOwnedWidget()->asType<UICodeEditor>()->removeClass( NOT_UNIQUE_FILENAME );
tab->setText( fileName );
}
bool dirty = doc->isDirty();
tab->removeClass( dirty ? "tab_clear" : "tab_modified" );
tab->addClass( dirty ? "tab_modified" : "tab_clear" );
bool dirty = doc->isDirty();
tab->removeClass( dirty ? "tab_clear" : "tab_modified" );
tab->addClass( dirty ? "tab_modified" : "tab_clear" );
} );
}
}
@@ -886,14 +890,9 @@ void App::onTextDropped( String text ) {
App::App( const size_t& jobs, const std::vector<std::string>& args ) :
mArgs( args ),
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
mThreadPool( ThreadPool::createShared( jobs > 0 ? jobs : eemax<int>( 2, Sys::getCPUCount() ) ) )
#elif defined( __EMSCRIPTEN_PTHREADS__ )
mThreadPool( ThreadPool::createShared( jobs > 0 ? jobs : eemin<int>( 8, Sys::getCPUCount() ) ) )
#endif
,
mSettingsActions( std::make_unique<SettingsActions>( this ) ) {
}
mThreadPool(
ThreadPool::createShared( jobs > 0 ? jobs : eemax<int>( 4, Sys::getCPUCount() ) ) ),
mSettingsActions( std::make_unique<SettingsActions>( this ) ) {}
static void fsRemoveAll( const std::string& fpath ) {
#if EE_PLATFORM == EE_PLATFORM_WIN
@@ -2182,9 +2181,7 @@ void App::loadImageFromMedium( const std::string& path, bool isMemory ) {
if ( imageView ) {
mImageLayout->setEnabled( true )->setVisible( true );
loaderView->setVisible( true );
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
mThreadPool->run( [this, imageView, loaderView, path, isMemory]() {
#endif
Image::Format format =
isMemory ? Image::getFormat( reinterpret_cast<const unsigned char*>( path.c_str() ),
path.size() )
@@ -2221,9 +2218,7 @@ void App::loadImageFromMedium( const std::string& path, bool isMemory ) {
imageView->setDrawable( nullptr );
loaderView->setVisible( false );
}
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
} );
#endif
}
}

View File

@@ -1,5 +1,5 @@
#include "ecode.hpp"
#include "globalsearchcontroller.hpp"
#include "ecode.hpp"
#include "uitreeviewglobalsearch.hpp"
namespace ecode {
@@ -53,18 +53,127 @@ static bool replaceInFile( const std::string& path, const std::vector<std::strin
return true;
}
size_t GlobalSearchController::replaceInFiles( const std::string& replaceText,
std::shared_ptr<ProjectSearch::ResultModel> model ) {
size_t count = 0;
static std::string getReplaceText( const ProjectSearch::ResultData::Result& result,
const std::string& replaceText ) {
std::string newText( replaceText );
LuaPattern ptrn( "$(%d+)" );
for ( auto& match : ptrn.gmatch( replaceText ) ) {
std::string matchSubStr( match.group( 0 ) ); // $1, $2, etc.
std::string matchNum( match.group( 1 ) ); // 1, 2, etc.
int num;
if ( String::fromString( num, matchNum ) && num > 0 &&
num - 1 < static_cast<int>( result.captures.size() ) ) {
String::replaceAll( newText, matchSubStr, result.captures[num - 1] );
}
}
return newText;
}
void GlobalSearchController::processNextReplaceInBuffer(
std::string&& replaceText, ProjectSearch::SearchConfig&& searchConfig,
std::function<void( int )>&& onDoneCb, int count,
std::vector<ProjectSearch::ResultData>&& pendingRes, bool hasCaptures ) {
if ( pendingRes.empty() ) {
onDoneCb( count );
return;
}
auto current = std::move( pendingRes.back() );
pendingRes.pop_back();
auto doc = mSplitter->findDocFromPath( current.file );
if ( doc ) {
auto results =
ProjectSearch::fileResFromDoc( searchConfig.searchString, searchConfig.caseSensitive,
searchConfig.wholeWord, searchConfig.type, doc );
for ( const auto& result : results ) {
if ( result.selected ) {
auto oldSel = doc->getSelections();
doc->setSelection( result.position );
doc->replaceSelection( hasCaptures ? getReplaceText( result, replaceText )
: replaceText );
count++;
}
}
processNextReplaceInBuffer( std::move( replaceText ), std::move( searchConfig ),
std::move( onDoneCb ), count, std::move( pendingRes ),
hasCaptures );
} else {
mSplitter->loadAsyncFileFromPathInNewTab(
current.file,
[this, current, count, pendingRes = std::move( pendingRes ),
replaceText = std::move( replaceText ), searchConfig = std::move( searchConfig ),
onDoneCb = std::move( onDoneCb ),
hasCaptures]( UICodeEditor* editor, const std::string& ) mutable {
auto doc = editor->getDocumentRef();
auto results = ProjectSearch::fileResFromDoc(
searchConfig.searchString, searchConfig.caseSensitive, searchConfig.wholeWord,
searchConfig.type, doc );
for ( const auto& result : results ) {
if ( result.selected ) {
auto oldSel = doc->getSelections();
doc->setSelection( result.position );
doc->replaceSelection( hasCaptures ? getReplaceText( result, replaceText )
: replaceText );
count++;
}
}
editor->scrollToCursor( true );
processNextReplaceInBuffer( std::move( replaceText ), std::move( searchConfig ),
std::move( onDoneCb ), count, std::move( pendingRes ),
hasCaptures );
} );
}
}
void GlobalSearchController::replaceInFiles( std::string replaceText,
std::shared_ptr<ProjectSearch::ResultModel> model,
std::function<void( int )> onDoneCb,
bool bufferOnlyMode,
ProjectSearch::SearchConfig searchConfig ) {
int count = 0;
if ( model->isResultFromSymbolReference() ) {
// TODO Implement replacement from result from symbol reference
return count;
return onDoneCb( count );
}
const ProjectSearch::Result& res = model->getResult();
bool hasCaptures =
model->isResultFromPatternMatch() && LuaPattern::hasMatches( replaceText, "$%d+" );
if ( bufferOnlyMode ) {
std::vector<ProjectSearch::ResultData> pendingResults;
for ( const auto& fileResult : res ) {
if ( !fileResult.selected )
continue;
if ( fileResult.openDoc ) {
for ( const auto& result : fileResult.results ) {
if ( !result.selected )
continue;
auto oldSel = fileResult.openDoc->getSelections();
fileResult.openDoc->setSelection( result.position );
fileResult.openDoc->replaceSelection(
hasCaptures ? getReplaceText( result, replaceText ) : replaceText );
fileResult.openDoc->setSelection( oldSel );
count++;
}
} else {
pendingResults.push_back( fileResult );
}
}
if ( pendingResults.empty() ) {
onDoneCb( count );
} else {
processNextReplaceInBuffer( std::move( replaceText ), std::move( searchConfig ),
std::move( onDoneCb ), count, std::move( pendingResults ),
hasCaptures );
}
return;
}
if ( hasCaptures ) {
for ( const auto& fileResult : res ) {
std::vector<std::pair<Int64, Int64>> replacements;
@@ -73,24 +182,14 @@ size_t GlobalSearchController::replaceInFiles( const std::string& replaceText,
for ( const auto& result : fileResult.results ) {
if ( !result.selected )
continue;
std::string newText( replaceText );
LuaPattern ptrn( "$(%d+)" );
for ( auto& match : ptrn.gmatch( replaceText ) ) {
std::string matchSubStr( match.group( 0 ) ); // $1 $2 ...
std::string matchNum( match.group( 1 ) ); // 1 2 ...
int num;
if ( String::fromString( num, matchNum ) && num > 0 &&
num - 1 < static_cast<int>( result.captures.size() ) ) {
String::replaceAll( newText, matchSubStr, result.captures[num - 1] );
replaceTexts.emplace_back( std::move( newText ) );
}
}
if ( result.openDoc ) {
auto oldSel = result.openDoc->getSelections();
result.openDoc->setSelection( result.position );
result.openDoc->replaceSelection( replaceTexts[replaceTexts.size() - 1] );
result.openDoc->setSelection( oldSel );
replaceTexts.emplace_back( getReplaceText( result, replaceText ) );
if ( fileResult.openDoc ) {
auto oldSel = fileResult.openDoc->getSelections();
fileResult.openDoc->setSelection( result.position );
fileResult.openDoc->replaceSelection( replaceTexts.back() );
fileResult.openDoc->setSelection( oldSel );
count++;
} else {
replacements.push_back( { result.start, result.end } );
@@ -99,33 +198,33 @@ size_t GlobalSearchController::replaceInFiles( const std::string& replaceText,
if ( replacements.size() == replaceTexts.size() &&
replaceInFile( fileResult.file, replaceTexts, replacements ) )
count += replacements.size();
count += static_cast<int>( replacements.size() );
}
return count;
return onDoneCb( count );
}
for ( const auto& fileResult : res ) {
std::vector<std::pair<Int64, Int64>> replacements;
for ( const auto& result : fileResult.results )
for ( const auto& result : fileResult.results ) {
if ( result.selected ) {
if ( result.openDoc ) {
auto oldSel = result.openDoc->getSelections();
result.openDoc->setSelection( result.position );
result.openDoc->replaceSelection( replaceText );
result.openDoc->setSelection( oldSel );
if ( fileResult.openDoc ) {
auto oldSel = fileResult.openDoc->getSelections();
fileResult.openDoc->setSelection( result.position );
fileResult.openDoc->replaceSelection( replaceText );
fileResult.openDoc->setSelection( oldSel );
count++;
} else {
replacements.push_back( { result.start, result.end } );
}
}
}
if ( !replacements.empty() && replaceInFile( fileResult.file, replaceText, replacements ) )
count += replacements.size();
count += static_cast<int>( replacements.size() );
}
return count;
onDoneCb( count );
}
void GlobalSearchController::showGlobalSearch() {
@@ -178,6 +277,12 @@ void GlobalSearchController::initGlobalSearchBar(
escapeSequenceChk->setTooltipText( escapeSequenceChk->getTooltipText() + " (" +
kbindEscape + ")" );
UICheckBox* bufferOnlyModeChk = mGlobalSearchBarLayout->find<UICheckBox>( "buffer_only_mode" );
std::string kbindBufferOnlyMode = kbind.getCommandKeybindString( "buffer-only-mode" );
if ( !kbindBufferOnlyMode.empty() )
bufferOnlyModeChk->setTooltipText( bufferOnlyModeChk->getTooltipText() + " (" +
kbindBufferOnlyMode + ")" );
UIWidget* searchBarClose = mGlobalSearchBarLayout->find<UIWidget>( "global_searchbar_close" );
caseSensitiveChk->setChecked( globalSearchBarConfig.caseSensitive );
@@ -185,6 +290,7 @@ void GlobalSearchController::initGlobalSearchBar(
luaPatternChk->setChecked( globalSearchBarConfig.luaPattern );
wholeWordChk->setChecked( globalSearchBarConfig.wholeWord );
escapeSequenceChk->setChecked( globalSearchBarConfig.escapeSequence );
bufferOnlyModeChk->setChecked( globalSearchBarConfig.bufferOnlyMode );
mGlobalSearchInput = mGlobalSearchBarLayout->find<UITextInput>( "global_search_find" );
mGlobalSearchWhereInput = mGlobalSearchBarLayout->find<UITextInput>( "global_search_where" );
@@ -192,20 +298,20 @@ void GlobalSearchController::initGlobalSearchBar(
mGlobalSearchHistoryList =
mGlobalSearchBarLayout->find<UIDropDownList>( "global_search_history" );
mGlobalSearchBarLayout->setCommand( "global-search-clear-history", [this] { clearHistory(); } );
mGlobalSearchBarLayout->setCommand(
"search-in-files",
[this, caseSensitiveChk, wholeWordChk, luaPatternChk, escapeSequenceChk, regexChk] {
doGlobalSearch( mGlobalSearchInput->getText(), mGlobalSearchWhereInput->getText(),
caseSensitiveChk->isChecked(), wholeWordChk->isChecked(),
luaPatternChk->isChecked()
? TextDocument::FindReplaceType::LuaPattern
: ( regexChk->isChecked() ? TextDocument::FindReplaceType::RegEx
: TextDocument::FindReplaceType::Normal ),
escapeSequenceChk->isChecked(), false );
} );
mGlobalSearchBarLayout->setCommand( "search-in-files", [this, caseSensitiveChk, wholeWordChk,
luaPatternChk, escapeSequenceChk,
regexChk, bufferOnlyModeChk] {
doGlobalSearch( mGlobalSearchInput->getText(), mGlobalSearchWhereInput->getText(),
caseSensitiveChk->isChecked(), wholeWordChk->isChecked(),
luaPatternChk->isChecked()
? TextDocument::FindReplaceType::LuaPattern
: ( regexChk->isChecked() ? TextDocument::FindReplaceType::RegEx
: TextDocument::FindReplaceType::Normal ),
escapeSequenceChk->isChecked(), bufferOnlyModeChk->isChecked(), false );
} );
mGlobalSearchBarLayout->setCommand( "search-again", [this, caseSensitiveChk, wholeWordChk,
luaPatternChk, escapeSequenceChk,
regexChk] {
bufferOnlyModeChk, regexChk] {
auto listBox = mGlobalSearchHistoryList->getListBox();
if ( listBox->getItemSelectedIndex() < mGlobalSearchHistory.size() ) {
const auto& item = mGlobalSearchHistory[mGlobalSearchHistory.size() - 1 -
@@ -216,7 +322,7 @@ void GlobalSearchController::initGlobalSearchBar(
? TextDocument::FindReplaceType::LuaPattern
: ( regexChk->isChecked() ? TextDocument::FindReplaceType::RegEx
: TextDocument::FindReplaceType::Normal ),
escapeSequenceChk->isChecked(),
escapeSequenceChk->isChecked(), bufferOnlyModeChk->isChecked(),
mGlobalSearchTreeReplace == mGlobalSearchTree, true );
}
} );
@@ -254,6 +360,9 @@ void GlobalSearchController::initGlobalSearchBar(
mGlobalSearchBarLayout->setCommand( "change-escape-sequence", [escapeSequenceChk] {
escapeSequenceChk->setChecked( !escapeSequenceChk->isChecked() );
} );
mGlobalSearchBarLayout->setCommand( "buffer-only-mode", [bufferOnlyModeChk] {
bufferOnlyModeChk->setChecked( !bufferOnlyModeChk->isChecked() );
} );
mGlobalSearchBarLayout->setCommand( "find-replace", [this] { mApp->showFindView(); } );
const auto pressEnterCb = [this]( const Event* event ) {
if ( event->getNode()->hasFocus() ) {
@@ -362,35 +471,35 @@ void GlobalSearchController::initGlobalSearchBar(
}
mGlobalSearchBarLayout->forceKeyDown( *keyEvent );
} );
mGlobalSearchBarLayout->setCommand( "search-replace-in-files", [this, caseSensitiveChk,
wholeWordChk, luaPatternChk,
escapeSequenceChk, replaceInput,
regexChk] {
if ( mGlobalSearchTreeReplace == mGlobalSearchTree ) {
replaceInput->setFocus();
replaceInput->getDocument().selectAll();
return;
}
// TODO Implement replacement from result from symbol reference
/*if ( mGlobalSearchHistory.back().second->isResultFromSymbolReference() ) {
mGlobalSearchTreeReplace->setModel( mGlobalSearchHistory.back().second );
showGlobalSearch( true );
updateGlobalSearchBarResults( mGlobalSearchHistory.back().first,
mGlobalSearchHistory.back().second, true, false );
} else*/
{
doGlobalSearch( mGlobalSearchInput->getText(), mGlobalSearchWhereInput->getText(),
caseSensitiveChk->isChecked(), wholeWordChk->isChecked(),
luaPatternChk->isChecked()
? TextDocument::FindReplaceType::LuaPattern
: ( regexChk->isChecked() ? TextDocument::FindReplaceType::RegEx
: TextDocument::FindReplaceType::Normal ),
escapeSequenceChk->isChecked(), true );
}
} );
mGlobalSearchBarLayout->setCommand(
"replace-in-files", [this, replaceInput, escapeSequenceChk] {
"search-replace-in-files", [this, caseSensitiveChk, wholeWordChk, luaPatternChk,
escapeSequenceChk, bufferOnlyModeChk, replaceInput, regexChk] {
if ( mGlobalSearchTreeReplace == mGlobalSearchTree ) {
replaceInput->setFocus();
replaceInput->getDocument().selectAll();
return;
}
// TODO Implement replacement from result from symbol reference
/*if ( mGlobalSearchHistory.back().second->isResultFromSymbolReference() ) {
mGlobalSearchTreeReplace->setModel( mGlobalSearchHistory.back().second );
showGlobalSearch( true );
updateGlobalSearchBarResults( mGlobalSearchHistory.back().first,
mGlobalSearchHistory.back().second, true, false );
} else*/
{
doGlobalSearch(
mGlobalSearchInput->getText(), mGlobalSearchWhereInput->getText(),
caseSensitiveChk->isChecked(), wholeWordChk->isChecked(),
luaPatternChk->isChecked()
? TextDocument::FindReplaceType::LuaPattern
: ( regexChk->isChecked() ? TextDocument::FindReplaceType::RegEx
: TextDocument::FindReplaceType::Normal ),
escapeSequenceChk->isChecked(), bufferOnlyModeChk->isChecked(), true );
}
} );
mGlobalSearchBarLayout->setCommand(
"replace-in-files", [this, replaceInput, escapeSequenceChk, bufferOnlyModeChk] {
auto listBox = mGlobalSearchHistoryList->getListBox();
if ( listBox->getItemSelectedIndex() < mGlobalSearchHistory.size() ) {
const auto& replaceData = mGlobalSearchHistory[mGlobalSearchHistory.size() - 1 -
@@ -398,11 +507,17 @@ void GlobalSearchController::initGlobalSearchBar(
String text( replaceInput->getText() );
if ( escapeSequenceChk->isChecked() )
text.unescape();
size_t count = replaceInFiles( text.toUtf8(), replaceData.result );
mGlobalSearchBarLayout->execute( "search-again" );
mGlobalSearchBarLayout->execute( "close-global-searchbar" );
mApp->getNotificationCenter()->addNotification(
String::format( "Replaced %zu occurrences.", count ) );
replaceInFiles(
text.toUtf8(), replaceData.result,
[this]( int count ) {
mGlobalSearchBarLayout->ensureMainThread( [this, count] {
mGlobalSearchBarLayout->execute( "search-again" );
mGlobalSearchBarLayout->execute( "close-global-searchbar" );
mApp->getNotificationCenter()->addNotification(
String::format( "Replaced %zu occurrences.", count ) );
} );
},
bufferOnlyModeChk->isChecked(), mLastSearchConfig );
}
} );
mGlobalSearchTreeSearch =
@@ -483,6 +598,7 @@ void GlobalSearchController::showGlobalSearch( bool searchReplace ) {
loader->setVisible( true );
if ( !searchReplace ) {
mGlobalSearchLayout->findByClass( "replace_box" )->setVisible( searchReplace );
mGlobalSearchBarLayout->find( "buffer_only_mode" )->setVisible( searchReplace );
if ( wasReplaceTree ) {
updateGlobalSearchBarResults( mGlobalSearchTreeReplace->getSearchStr(),
std::static_pointer_cast<ProjectSearch::ResultModel>(
@@ -523,12 +639,14 @@ GlobalSearchBarConfig GlobalSearchController::getGlobalSearchBarConfig() const {
UICheckBox* regexChk = mGlobalSearchBarLayout->find<UICheckBox>( "regex" );
UICheckBox* luaPatternChk = mGlobalSearchBarLayout->find<UICheckBox>( "lua_pattern" );
UICheckBox* escapeSequenceChk = mGlobalSearchBarLayout->find<UICheckBox>( "escape_sequence" );
UICheckBox* bufferOnlyModeChk = mGlobalSearchBarLayout->find<UICheckBox>( "buffer_only_mode" );
GlobalSearchBarConfig globalSeachBarConfig;
globalSeachBarConfig.caseSensitive = caseSensitiveChk->isChecked();
globalSeachBarConfig.regex = regexChk->isChecked();
globalSeachBarConfig.luaPattern = luaPatternChk->isChecked();
globalSeachBarConfig.wholeWord = wholeWordChk->isChecked();
globalSeachBarConfig.escapeSequence = escapeSequenceChk->isChecked();
globalSeachBarConfig.bufferOnlyMode = bufferOnlyModeChk->isChecked();
return globalSeachBarConfig;
}
@@ -581,6 +699,7 @@ void GlobalSearchController::updateGlobalSearchBarResults(
->setText( String::format( "%zu matches found.", model->resultCount() ) );
mGlobalSearchLayout->findByClass( "status_box" )->setVisible( true );
mGlobalSearchLayout->findByClass( "replace_box" )->setVisible( searchReplace );
mGlobalSearchBarLayout->find( "buffer_only_mode" )->setVisible( searchReplace );
if ( searchReplace && mGlobalSearchBarLayout->isVisible() ) {
auto* replaceInput =
mGlobalSearchLayout->find<UITextInput>( "global_search_replace_input" );
@@ -641,8 +760,8 @@ std::vector<GlobMatch> GlobalSearchController::parseGlobMatches( const String& s
void GlobalSearchController::doGlobalSearch( String text, String filter, bool caseSensitive,
bool wholeWord,
TextDocument::FindReplaceType searchType,
bool escapeSequence, bool searchReplace,
bool searchAgain ) {
bool escapeSequence, bool bufferOnlyMode,
bool searchReplace, bool searchAgain ) {
if ( mApp->getDirTree() && mApp->getDirTree()->getFilesCount() > 0 && !text.empty() ) {
mGlobalSearchTree = searchReplace ? mGlobalSearchTreeReplace : mGlobalSearchTreeSearch;
mGlobalSearchTreeSearch->setVisible( !searchReplace );
@@ -684,17 +803,16 @@ void GlobalSearchController::doGlobalSearch( String text, String filter, bool ca
}
ProjectSearch::find(
mApp->getDirTree()->getFiles(), search,
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
mApp->getThreadPool(),
#endif
mApp->getDirTree()->getFiles(), search, mApp->getThreadPool(),
[this, clock, search, loader, searchReplace, searchAgain, escapeSequence, searchType,
filter]( const ProjectSearch::Result& res ) {
filter]( const ProjectSearch::ConsolidatedResult& res ) {
Log::info( "Global search for \"%s\" took %s", search.c_str(),
clock.getElapsedTime().toString() );
mUISceneNode->runOnMainThread( [this, loader, res, search, searchReplace,
searchAgain, escapeSequence, searchType, filter] {
auto model = ProjectSearch::asModel( res );
mUISceneNode->runOnMainThread( [this, loader, res = std::move( res ), search,
searchReplace, searchAgain, escapeSequence,
searchType, filter] {
mLastSearchConfig = std::move( res.first );
auto model = ProjectSearch::asModel( res.second );
model->setOpType( searchType );
updateGlobalSearchHistory( model, search, filter, searchReplace, searchAgain,
escapeSequence );

View File

@@ -27,6 +27,7 @@ class GlobalSearchController {
{ "mod+shift+e", "collapse-all" },
{ "mod+e", "change-escape-sequence" },
{ "mod+h", "global-search-clear-history" },
{ "mod+b", "buffer-only-mode" },
};
}
@@ -50,10 +51,7 @@ class GlobalSearchController {
void doGlobalSearch( String text, String filter, bool caseSensitive, bool wholeWord,
TextDocument::FindReplaceType searchType, bool escapeSequence,
bool searchReplace, bool searchAgain = false );
size_t replaceInFiles( const std::string& replaceText,
std::shared_ptr<ProjectSearch::ResultModel> model );
bool bufferOnlyMode, bool searchReplace, bool searchAgain = false );
void showGlobalSearch();
@@ -88,6 +86,7 @@ class GlobalSearchController {
};
std::deque<SearchHistoryItem> mGlobalSearchHistory;
bool mValueChanging{ false };
ProjectSearch::SearchConfig mLastSearchConfig;
void onLoadDone( const Variant& lineNum, const Variant& colNum );
@@ -98,6 +97,16 @@ class GlobalSearchController {
bool searchReplace, bool searchAgain, bool escapeSequence );
std::vector<GlobMatch> parseGlobMatches( const String& str );
void replaceInFiles( std::string replaceText, std::shared_ptr<ProjectSearch::ResultModel> model,
std::function<void( int )> onDoneCb, bool bufferOnlyMode,
ProjectSearch::SearchConfig searchConfig );
void processNextReplaceInBuffer( std::string&& replaceText,
ProjectSearch::SearchConfig&& searchConfig,
std::function<void( int )>&& onDoneCb, int count,
std::vector<ProjectSearch::ResultData>&& pendingRes,
bool hasCaptures );
};
} // namespace ecode

View File

@@ -10,12 +10,6 @@
using json = nlohmann::json;
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define AIASSISTANT_THREADED 1
#else
#define AIASSISTANT_THREADED 0
#endif
namespace ecode {
static std::initializer_list<std::string> AIAssistantUnlockedCommandList = {
@@ -126,11 +120,7 @@ AIAssistantPlugin::AIAssistantPlugin( PluginManager* pluginManager, bool sync )
if ( sync ) {
load( pluginManager );
} else {
#if defined( AIASSISTANT_THREADED ) && AIASSISTANT_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
if ( getUISceneNode() ) {

View File

@@ -23,12 +23,6 @@ static constexpr auto SNIPPET_PTRN1 = "%$%{%d+%}"sv;
static constexpr auto SNIPPET_PTRN2 = "%$%{%d+%:([%w,.%s%+%-]+)}"sv;
static constexpr auto SNIPPET_PTRN3 = "%$%d+"sv;
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define AUTO_COMPLETE_THREADED 1
#else
#define AUTO_COMPLETE_THREADED 0
#endif
static json getURIJSON( TextDocument* doc, const PluginIDType& id ) {
json data;
data["uri"] = doc->getURI().toString();
@@ -102,11 +96,7 @@ AutoCompletePlugin::AutoCompletePlugin( PluginManager* pluginManager, bool sync
if ( sync ) {
load( pluginManager );
} else {
#if defined( AUTO_COMPLETE_THREADED ) && AUTO_COMPLETE_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}
@@ -317,15 +307,10 @@ void AutoCompletePlugin::onRegister( UICodeEditor* editor ) {
const DocSyntaxDefEvent* event = static_cast<const DocSyntaxDefEvent*>( ev );
std::string oldLang = event->getOldLang();
std::string newLang = event->getNewLang();
#if defined( AUTO_COMPLETE_THREADED ) && AUTO_COMPLETE_THREADED == 1
mThreadPool->run( [this, oldLang, newLang] {
updateLangCache( oldLang );
updateLangCache( newLang );
} );
#else
updateLangCache( oldLang );
updateLangCache( newLang );
#endif
} ) );
if ( editor->hasDocument() ) {
@@ -1009,11 +994,7 @@ void AutoCompletePlugin::update( UICodeEditor* ) {
if ( du != mDocsUpdating.end() && du->second == true )
continue;
}
#if AUTO_COMPLETE_THREADED
mThreadPool->run( [this, doc] { updateDocCache( doc ); } );
#else
updateDocCache( doc );
#endif
}
}
}
@@ -1475,13 +1456,9 @@ void AutoCompletePlugin::updateSuggestions( const std::string& symbol, UICodeEdi
return;
const auto& symbols = docCache->second.symbols;
{
#if AUTO_COMPLETE_THREADED
mThreadPool->run( [this, symbol, &symbols, editor] {
runUpdateSuggestions( symbol, symbols, editor, true );
} );
#else
runUpdateSuggestions( symbol, symbols, editor, true );
#endif
}
}
@@ -1492,13 +1469,9 @@ void AutoCompletePlugin::updateSuggestions( const std::string& symbol, UICodeEdi
return;
const auto& symbols = langSuggestions->second;
{
#if AUTO_COMPLETE_THREADED
mThreadPool->run( [this, symbol, &symbols, editor] {
runUpdateSuggestions( symbol, symbols, editor, false );
} );
#else
runUpdateSuggestions( symbol, symbols, editor, false );
#endif
}
}

View File

@@ -28,12 +28,6 @@ using json = nlohmann::json;
static constexpr auto REQUEST_TYPE_LAUNCH = "launch";
static constexpr auto REQUEST_TYPE_ATTACH = "attach";
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define DEBUGGER_THREADED 1
#else
#define DEBUGGER_THREADED 0
#endif
namespace ecode {
static constexpr auto INPUT_PATTERN = "%$%{input%:([%w_]+)%}"sv;
@@ -143,11 +137,7 @@ DebuggerPlugin::DebuggerPlugin( PluginManager* pluginManager, bool sync ) :
if ( sync ) {
load( pluginManager );
} else {
#if defined( DEBUGGER_THREADED ) && DEBUGGER_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}

View File

@@ -1,11 +1,6 @@
#include "discordRPCplugin.hpp"
using json = nlohmann::json;
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define dcRPC_THREADED 1
#else
#define dcRPC_THREADED 0
#endif
namespace ecode {
@@ -29,11 +24,7 @@ DiscordRPCplugin::DiscordRPCplugin( PluginManager* pluginManager, bool sync ) :
if ( sync ) {
load( pluginManager );
} else {
#if defined( dcRPC_THREADED ) && dcRPC_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}

View File

@@ -17,12 +17,6 @@ using json = nlohmann::json;
namespace ecode {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define FORMATTER_THREADED 1
#else
#define FORMATTER_THREADED 0
#endif
Plugin* FormatterPlugin::New( PluginManager* pluginManager ) {
return eeNew( FormatterPlugin, ( pluginManager, false ) );
}
@@ -36,11 +30,7 @@ FormatterPlugin::FormatterPlugin( PluginManager* pluginManager, bool sync ) :
if ( sync ) {
load( pluginManager );
} else {
#if defined( FORMATTER_THREADED ) && FORMATTER_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}

View File

@@ -26,11 +26,6 @@ using namespace EE::UI::Doc;
using namespace std::literals;
using json = nlohmann::json;
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define GIT_THREADED 1
#else
#define GIT_THREADED 0
#endif
namespace ecode {
@@ -74,11 +69,7 @@ GitPlugin::GitPlugin( PluginManager* pluginManager, bool sync ) :
if ( sync ) {
load( pluginManager );
} else {
#if defined( GIT_THREADED ) && GIT_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}

View File

@@ -20,12 +20,6 @@ using json = nlohmann::json;
namespace ecode {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define LINTER_THREADED 1
#else
#define LINTER_THREADED 0
#endif
Plugin* LinterPlugin::New( PluginManager* pluginManager ) {
return eeNew( LinterPlugin, ( pluginManager, false ) );
}
@@ -38,11 +32,7 @@ LinterPlugin::LinterPlugin( PluginManager* pluginManager, bool sync ) : Plugin(
if ( sync ) {
load( pluginManager );
} else {
#if defined( LINTER_THREADED ) && LINTER_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}
@@ -713,11 +703,7 @@ void LinterPlugin::update( UICodeEditor* editor ) {
auto it = mDirtyDoc.find( doc.get() );
if ( it != mDirtyDoc.end() && it->second->getElapsedTime() >= mDelayTime ) {
mDirtyDoc.erase( doc.get() );
#if LINTER_THREADED
mThreadPool->run( [this, doc] { lintDoc( doc ); } );
#else
lintDoc( doc );
#endif
}
}

View File

@@ -25,12 +25,6 @@ using json = nlohmann::json;
namespace ecode {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define LSPCLIENT_THREADED 1
#else
#define LSPCLIENT_THREADED 0
#endif
static Action::UniqueID getMouseMoveHash( UICodeEditor* editor ) {
return hashCombine( String::hash( "LSPClientPlugin::onMouseMove-" ),
reinterpret_cast<Action::UniqueID>( editor ) );
@@ -245,11 +239,7 @@ LSPClientPlugin::LSPClientPlugin( PluginManager* pluginManager, bool sync ) :
if ( sync ) {
load( pluginManager );
} else {
#if defined( LSPCLIENT_THREADED ) && LSPCLIENT_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}

View File

@@ -5,11 +5,6 @@
#include <nlohmann/json.hpp>
using json = nlohmann::json;
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
#define XMLTOOLS_THREADED 1
#else
#define XMLTOOLS_THREADED 0
#endif
namespace ecode {
@@ -26,11 +21,7 @@ XMLToolsPlugin::XMLToolsPlugin( PluginManager* pluginManager, bool sync ) :
if ( sync ) {
load( pluginManager );
} else {
#if defined( XMLTOOLS_THREADED ) && XMLTOOLS_THREADED == 1
mThreadPool->run( [this, pluginManager] { load( pluginManager ); } );
#else
load( pluginManager );
#endif
}
}

View File

@@ -39,10 +39,8 @@ ProjectDirectoryTree::~ProjectDirectoryTree() {
void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent& scanComplete,
const std::vector<std::string>& acceptedPatterns,
const bool& ignoreHidden ) {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
mPool->run(
[this, acceptedPatterns = std::move( acceptedPatterns ), ignoreHidden] {
#endif
Lock l( mFilesMutex );
mRunning = true;
mIgnoreHidden = ignoreHidden;
@@ -93,11 +91,6 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent&
return processMessage( msg );
} );
}
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN && !defined( __EMSCRIPTEN_PTHREADS__ )
if ( scanComplete )
scanComplete( *this );
#endif
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
},
[scanComplete, this]( const auto& ) {
if ( !mClosing && scanComplete ) {
@@ -106,7 +99,6 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent&
}
mRunning = false;
} );
#endif
}
std::shared_ptr<FileListModel>

View File

@@ -159,44 +159,6 @@ static std::vector<ProjectSearch::ResultData::Result> searchInFileRegEx( const s
return searchInFilePatternMatch( file, pattern, caseSensitive, wholeWord );
}
void ProjectSearch::find( const std::vector<std::string> files, const std::string& string,
ResultCb result, bool caseSensitive, bool wholeWord,
const TextDocument::FindReplaceType& type,
const std::vector<GlobMatch>& pathFilters, std::string basePath,
std::vector<std::shared_ptr<TextDocument>> ) {
Result res;
const auto occ =
type == TextDocument::FindReplaceType::Normal
? String::BMH::createOccTable( (const unsigned char*)string.c_str(), string.size() )
: std::vector<size_t>();
for ( auto& file : files ) {
bool skip = false;
std::string_view fsv( file );
if ( !basePath.empty() && String::startsWith( file, basePath ) )
fsv = fsv.substr( basePath.size() );
for ( const auto& filter : pathFilters ) {
bool matches = String::globMatch( fsv, filter.first );
if ( ( matches && filter.second ) || ( !matches && !filter.second ) ) {
skip = true;
break;
}
}
if ( skip )
continue;
auto fileRes =
type == TextDocument::FindReplaceType::Normal
? searchInFileHorspool( file, string, caseSensitive, wholeWord, occ )
: ( type == TextDocument::FindReplaceType::LuaPattern
? searchInFileLuaPattern( file, string, caseSensitive, wholeWord )
: searchInFileRegEx( file, string, caseSensitive, wholeWord ) );
if ( !fileRes.empty() )
res.push_back( { file, fileRes } );
}
result( res );
}
struct FindData {
Mutex resMutex;
Mutex countMutex;
@@ -204,6 +166,32 @@ struct FindData {
ProjectSearch::Result res;
};
std::vector<ProjectSearch::ResultData::Result>
ProjectSearch::fileResFromDoc( const std::string& string, bool caseSensitive, bool wholeWord,
TextDocument::FindReplaceType type,
std::shared_ptr<TextDocument> doc ) {
auto res = doc->findAll( string, caseSensitive, wholeWord, type );
std::vector<ProjectSearch::ResultData::Result> fileRes;
for ( const auto& r : res ) {
ProjectSearch::ResultData::Result f;
f.position = r.result;
const auto& line = doc->line( r.result.start().line() );
if ( line.size() > EE_1KB )
f.line = line.substr( 0, EE_1KB );
else
f.line = line.getTextWithoutNewLine();
f.start = r.result.start().column();
f.end = r.result.end().column();
std::vector<std::string> captures;
for ( const auto& capture : r.captures )
captures.emplace_back( doc->getText( capture ).toUtf8() );
f.captures = std::move( captures );
fileRes.emplace_back( std::move( f ) );
}
return fileRes;
}
void ProjectSearch::find( const std::vector<std::string> files, std::string string,
std::shared_ptr<ThreadPool> pool, ResultCb result, bool caseSensitive,
bool wholeWord, const TextDocument::FindReplaceType& type,
@@ -216,6 +204,7 @@ void ProjectSearch::find( const std::vector<std::string> files, std::string stri
result = std::move( result ), caseSensitive, wholeWord, type,
pathFilters = std::move( pathFilters ), basePath = std::move( basePath ),
openDocs = std::move( openDocs )]() mutable {
SearchConfig searchConfig( string, caseSensitive, wholeWord, type );
FindData* findData = eeNew( FindData, () );
findData->resCount = files.size();
if ( !caseSensitive )
@@ -267,7 +256,7 @@ void ProjectSearch::find( const std::vector<std::string> files, std::string stri
findData->resCount = count;
if ( count == 0 ) {
result( findData->res );
result( { searchConfig, findData->res } );
eeDelete( findData );
return;
}
@@ -286,7 +275,7 @@ void ProjectSearch::find( const std::vector<std::string> files, std::string stri
pos++;
const auto onSearchEnd = [result, findData]( const auto& ) {
const auto onSearchEnd = [result, findData, searchConfig]( const auto& ) {
int count;
{
Lock l( findData->countMutex );
@@ -294,7 +283,7 @@ void ProjectSearch::find( const std::vector<std::string> files, std::string stri
count = findData->resCount;
}
if ( count == 0 ) {
result( findData->res );
result( { searchConfig, findData->res } );
eeDelete( findData );
#if EE_PLATFORM == EE_PLATFORM_LINUX && defined( __GLIBC__ )
malloc_trim( 0 );
@@ -311,30 +300,14 @@ void ProjectSearch::find( const std::vector<std::string> files, std::string stri
if ( openDoc && openPath->second->isDirty() ) {
pool->run(
[findData, doc, string, caseSensitive, wholeWord, type] {
auto res = doc->findAll( string, caseSensitive, wholeWord, type );
std::vector<ProjectSearch::ResultData::Result> fileRes;
for ( const auto& r : res ) {
ProjectSearch::ResultData::Result f;
f.openDoc = doc;
f.position = r.result;
const auto& line = doc->line( r.result.start().line() );
if ( line.size() > EE_1KB )
f.line = line.substr( 0, EE_1KB );
else
f.line = line.getTextWithoutNewLine();
f.start = r.result.start().column();
f.end = r.result.end().column();
std::vector<std::string> captures;
for ( const auto& capture : r.captures )
captures.emplace_back( doc->getText( capture ).toUtf8() );
f.captures = std::move( captures );
fileRes.emplace_back( std::move( f ) );
}
std::vector<ProjectSearch::ResultData::Result> fileRes =
fileResFromDoc( string, caseSensitive, wholeWord, type, doc );
if ( !fileRes.empty() ) {
Lock l( findData->resMutex );
std::string file( doc->getFilePath() );
findData->res.push_back( { std::move( file ), std::move( fileRes ) } );
findData->res.push_back(
{ std::move( file ), std::move( fileRes ), doc } );
}
},
onSearchEnd );

View File

@@ -21,6 +21,13 @@ using GlobMatch = std::pair<std::string, bool>; // where string is the glob and
class ProjectSearch {
public:
struct SearchConfig {
std::string searchString;
bool caseSensitive;
bool wholeWord;
TextDocument::FindReplaceType type;
};
struct ResultData {
struct Result {
Result( const String& line, const TextRange& pos, Int64 s, Int64 e ) :
@@ -32,10 +39,10 @@ class ProjectSearch {
Int64 end{ 0 };
bool selected{ true };
std::vector<std::string> captures;
std::shared_ptr<TextDocument> openDoc;
};
std::string file;
std::vector<Result> results;
std::shared_ptr<TextDocument> openDoc{ nullptr };
bool selected{ true };
void setResultsSelected( bool selected ) {
@@ -61,8 +68,9 @@ class ProjectSearch {
}
};
typedef std::vector<ResultData> Result;
typedef std::function<void( const Result& )> ResultCb;
using Result = std::vector<ResultData>;
using ConsolidatedResult = std::pair<SearchConfig, Result>;
using ResultCb = std::function<void( const ConsolidatedResult& )>;
class ResultModel : public Model {
public:
@@ -213,12 +221,9 @@ class ProjectSearch {
return std::make_shared<ResultModel>( result );
}
static void
find( const std::vector<std::string> files, const std::string& string, ResultCb result,
bool caseSensitive, bool wholeWord = false,
const TextDocument::FindReplaceType& type = TextDocument::FindReplaceType::Normal,
const std::vector<GlobMatch>& pathFilters = {}, std::string basePath = "",
std::vector<std::shared_ptr<TextDocument>> openDocs = {} );
static std::vector<ProjectSearch::ResultData::Result>
fileResFromDoc( const std::string& string, bool caseSensitive, bool wholeWord,
TextDocument::FindReplaceType type, std::shared_ptr<TextDocument> doc );
static void
find( const std::vector<std::string> files, std::string string,

View File

@@ -493,7 +493,6 @@ void StatusBuildOutputController::createContainer() {
onLoadDone( lineNum, colNum );
} );
} else {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
removeRelativeSubPaths( path );
mContext->getDirTree()->asyncMatchTree(
ProjectDirectoryTree::MatchType::Fuzzy, path, 1,
@@ -518,7 +517,6 @@ void StatusBuildOutputController::createContainer() {
}
} );
} );
#endif
}
} else {
tab->getTabWidget()->setTabSelected( tab );

View File

@@ -355,7 +355,6 @@ void UniversalLocator::updateFilesTable( bool useGlob ) {
ProjectDirectoryTree::emptyModel( getLocatorCommands(), mApp->getCurrentProject() ) );
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
} else if ( !mLocateInput->getText().empty() ) {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
mApp->getDirTree()->asyncMatchTree(
useGlob ? ProjectDirectoryTree::MatchType::Glob
: ProjectDirectoryTree::MatchType::Fuzzy,
@@ -369,15 +368,6 @@ void UniversalLocator::updateFilesTable( bool useGlob ) {
} );
},
mApp->getCurrentProject() );
#else
mLocateTable->setModel(
useGlob ? mApp->getDirTree()->globMatchTree( text, LOCATEBAR_MAX_RESULTS,
mApp->getCurrentProject() )
: mApp->getDirTree()->fuzzyMatchTree( text, LOCATEBAR_MAX_RESULTS,
mApp->getCurrentProject() ) );
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
mLocateTable->scrollToTop();
#endif
} else {
mLocateTable->setModel( mApp->getDirTree()->asModel(
LOCATEBAR_MAX_RESULTS, getLocatorCommands(), mApp->getCurrentProject(),
@@ -403,7 +393,6 @@ void UniversalLocator::updateCommandPaletteTable() {
txt.trim();
if ( txt.size() > 1 ) {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
mCommandPalette.asyncFuzzyMatch( txt.substr( 1 ).trim(), 10000, [this]( auto res ) {
mUISceneNode->runOnMainThread( [this, res] {
mLocateTable->setModel( res );
@@ -412,12 +401,6 @@ void UniversalLocator::updateCommandPaletteTable() {
mLocateTable->scrollToTop();
} );
} );
#else
mLocateTable->setModel( mCommandPalette.fuzzyMatch( txt.substr( 1 ).trim(), 10000 ) );
if ( mLocateTable->getModel()->hasChilds() )
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
mLocateTable->scrollToTop();
#endif
} else if ( mCommandPalette.getCurModel() ) {
mLocateTable->setModel( mCommandPalette.getCurModel() );
if ( mLocateTable->getModel()->hasChilds() )
@@ -1097,7 +1080,6 @@ void UniversalLocator::requestDocumentSymbol() {
}
void UniversalLocator::updateDocumentSymbol( const LSPSymbolInformationList& res ) {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
if ( mCurDocQuery.empty() ) {
mTextDocumentSymbolModel =
LSPSymbolInfoModel::create( mApp->getUISceneNode(), mCurDocQuery, res, true );
@@ -1114,21 +1096,6 @@ void UniversalLocator::updateDocumentSymbol( const LSPSymbolInformationList& res
} );
} );
}
#else
mUISceneNode->runOnMainThread( [this, res] {
if ( mCurDocQuery.empty() ) {
mTextDocumentSymbolModel =
LSPSymbolInfoModel::create( mApp->getUISceneNode(), mCurDocQuery, res, true );
} else {
mTextDocumentSymbolModel = LSPSymbolInfoModel::create(
mApp->getUISceneNode(), mCurDocQuery,
fuzzyMatchTextDocumentSymbol( res, mCurDocQuery, 100 ), true );
}
mLocateTable->setModel( mTextDocumentSymbolModel );
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
mLocateTable->scrollToTop();
} );
#endif
}
std::string UniversalLocator::getCurDocURI() {