mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-18 06:55:48 +03:00
Add RegEx support for global search.
Minor change in how minimap is dragged.
This commit is contained in:
@@ -1360,12 +1360,12 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags
|
||||
if ( !mMinimapHover && !mMouseDown ) {
|
||||
mMinimapScrollOffset = 0;
|
||||
scrollToVisibleIndex( calculateMinimapClickedLine( position ), false, true );
|
||||
return 1;
|
||||
} else {
|
||||
mMinimapScrollOffset = calculateMinimapClickedLine( position ) -
|
||||
static_cast<Int64>( getVisibleLineRange().first );
|
||||
}
|
||||
mMouseDown = true;
|
||||
mMouseDownMinimap = true;
|
||||
mMinimapScrollOffset = calculateMinimapClickedLine( position ) -
|
||||
static_cast<Int64>( getVisibleLineRange().first );
|
||||
mMinimapDragging = true;
|
||||
getEventDispatcher()->setNodeDragging( this );
|
||||
mVScrollBar->setEnabled( false );
|
||||
|
||||
@@ -40,14 +40,32 @@ UTEST( RegEx, cacheHit ) {
|
||||
RegExCache::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( RegEx, captures ) {
|
||||
RegEx regex( "(\\d+) and (\\d+)" );
|
||||
std::string testStr = "The number is 42 and 23.";
|
||||
PatternMatcher::Range matches[10];
|
||||
regex.matches( testStr, matches );
|
||||
ASSERT_EQ( regex.isValid(), true );
|
||||
ASSERT_EQ( regex.getNumMatches(), 3ul );
|
||||
EXPECT_EQ( matches[0].start, 14 );
|
||||
EXPECT_EQ( matches[0].end, 23 );
|
||||
EXPECT_EQ( matches[1].start, 14 );
|
||||
EXPECT_EQ( matches[1].end, 16 );
|
||||
EXPECT_EQ( matches[2].start, 21 );
|
||||
EXPECT_EQ( matches[2].end, 23 );
|
||||
RegExCache::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( RegEx, TextDocument ) {
|
||||
TextDocument doc;
|
||||
doc.textInput( "This number is 42.\nThe number is 69.\n" );
|
||||
doc.textInput( "This number is 42.\nThe number is 23.\n" );
|
||||
auto res = doc.findAll( "\\d+", true, false, TextDocument::FindReplaceType::RegEx );
|
||||
EXPECT_EQ( res.size(), 2ul );
|
||||
ASSERT_EQ( res.size(), 2ul );
|
||||
if ( res.size() == 2ul ) {
|
||||
EXPECT_EQ( res[0].isValid(), true );
|
||||
EXPECT_TRUE( res[0].result == TextRange( { 0, 15 }, { 0, 17 } ) );
|
||||
EXPECT_EQ( res[1].isValid(), true );
|
||||
EXPECT_TRUE( res[1].result == TextRange( { 1, 14 }, { 1, 16 } ) );
|
||||
}
|
||||
RegExCache::destroySingleton();
|
||||
}
|
||||
|
||||
@@ -188,6 +188,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
|
||||
globalSearchBarConfig.caseSensitive =
|
||||
ini.getValueB( "global_search_bar", "case_sensitive", false );
|
||||
globalSearchBarConfig.luaPattern = ini.getValueB( "global_search_bar", "lua_pattern", false );
|
||||
globalSearchBarConfig.regex = ini.getValueB( "global_search_bar", "regex", false );
|
||||
globalSearchBarConfig.wholeWord = ini.getValueB( "global_search_bar", "whole_word", false );
|
||||
globalSearchBarConfig.escapeSequence =
|
||||
ini.getValueB( "global_search_bar", "escape_sequence", false );
|
||||
@@ -327,6 +328,7 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
|
||||
ini.setValueB( "global_search_bar", "case_sensitive", globalSearchBarConfig.caseSensitive );
|
||||
ini.setValueB( "global_search_bar", "lua_pattern", globalSearchBarConfig.luaPattern );
|
||||
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 );
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ struct SearchBarConfig {
|
||||
|
||||
struct GlobalSearchBarConfig {
|
||||
bool caseSensitive{ false };
|
||||
bool regex{ false };
|
||||
bool luaPattern{ false };
|
||||
bool wholeWord{ false };
|
||||
bool escapeSequence{ false };
|
||||
|
||||
@@ -529,24 +529,24 @@ R"html(
|
||||
</RelativeLayout>
|
||||
</Splitter>
|
||||
<searchbar id="search_bar" lw="mp" lh="wc">
|
||||
<vbox lw="wc" lh="wc" margin-right="4dp">
|
||||
<vbox lw="wc" lh="wc" margin-right="4dp" layout-gravity="center">
|
||||
<TextView lw="wc" lh="18dp" text='@string("find_text", "Find:")' margin-bottom="2dp" />
|
||||
<TextView lw="wc" lh="18dp" text='@string("replace_with_text", "Replace with:")' />
|
||||
</vbox>
|
||||
<vbox lw="0" lw8="1" lh="wc" margin-right="4dp">
|
||||
<vbox lw="0" lw8="1" lh="wc" margin-right="4dp" layout-gravity="center">
|
||||
<TextInput id="search_find" lw="mp" lh="18dp" padding="0" margin-bottom="2dp" />
|
||||
<TextInput id="search_replace" lw="mp" lh="18dp" padding="0" />
|
||||
</vbox>
|
||||
<vbox lw="wc" lh="wc" margin-right="4dp">
|
||||
<vbox lw="wc" lh="wc" margin-right="4dp" layout-gravity="center">
|
||||
<CheckBox id="case_sensitive" lw="wc" lh="wc" text='@string(case_sensitive, "Case sensitive")' selected="false" />
|
||||
<CheckBox id="regex" lw="wc" lh="wc" text='@string(regular_expression, "Regular Expression")' selected="false" />
|
||||
<CheckBox id="lua_pattern" lw="wc" lh="wc" text='@string(lua_pattern, "Lua Pattern")' selected="false" />
|
||||
</vbox>
|
||||
<vbox lw="wc" lh="wc" margin-right="4dp">
|
||||
<vbox lw="wc" lh="wc" margin-right="4dp" layout-gravity="center">
|
||||
<CheckBox id="whole_word" lw="wc" lh="wc" text='@string(match_whole_word, "Match Whole Word")' selected="false" />
|
||||
<CheckBox id="escape_sequence" lw="wc" lh="wc" text='@string(use_escape_sequences, "Use escape sequences")' selected="false" tooltip='@string(escape_sequence_tooltip, "Replace \\, \\t, \\n, \\r and \\uXXXX (Unicode characters) with the corresponding control")' />
|
||||
</vbox>
|
||||
<vbox lw="wc" lh="wc">
|
||||
<vbox lw="wc" lh="wc" layout-gravity="center">
|
||||
<hbox lw="wc" lh="wc" margin-bottom="2dp">
|
||||
<PushButton id="find_prev" lw="wc" lh="18dp" text='@string(previous, "Previous")' margin-right="4dp" />
|
||||
<PushButton id="find_next" lw="wc" lh="18dp" text='@string(next, "Next")' margin-right="4dp" />"
|
||||
@@ -582,6 +582,7 @@ R"html(
|
||||
<StackLayout lw="mp" lh="wc" margin-bottom="2dp">
|
||||
<CheckBox id="case_sensitive" text='@string(case_sensitive, "Case sensitive")' selected="true" margin-right="8dp" />
|
||||
<CheckBox id="whole_word" text='@string(match_whole_word, "Match Whole Word")' selected="false" margin-right="8dp" />
|
||||
<CheckBox id="regex" text='@string(regular_expression, "Regular Expression")' selected="false" margin-right="8dp" />
|
||||
<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")' />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "ecode.hpp"
|
||||
#include "globalsearchcontroller.hpp"
|
||||
#include "ecode.hpp"
|
||||
#include "uitreeviewglobalsearch.hpp"
|
||||
|
||||
namespace ecode {
|
||||
@@ -62,8 +62,8 @@ size_t GlobalSearchController::replaceInFiles( const std::string& replaceText,
|
||||
}
|
||||
|
||||
const ProjectSearch::Result& res = model->getResult();
|
||||
bool hasCaptures =
|
||||
model->isResultFromLuaPattern() && LuaPattern::hasMatches( replaceText, "$%d+" );
|
||||
bool hasCaptures = ( model->isResultFromLuaPattern() || model->isResultFromRegEx() ) &&
|
||||
LuaPattern::hasMatches( replaceText, "$%d+" );
|
||||
|
||||
if ( hasCaptures ) {
|
||||
for ( const auto& fileResult : res ) {
|
||||
@@ -166,6 +166,9 @@ void GlobalSearchController::initGlobalSearchBar(
|
||||
UICheckBox* wholeWordChk = mGlobalSearchBarLayout->find<UICheckBox>( "whole_word" );
|
||||
wholeWordChk->setTooltipText( kbind.getCommandKeybindString( "change-whole-word" ) );
|
||||
|
||||
UICheckBox* regexChk = mGlobalSearchBarLayout->find<UICheckBox>( "regex" );
|
||||
regexChk->setTooltipText( kbind.getCommandKeybindString( "toggle-regex" ) );
|
||||
|
||||
UICheckBox* luaPatternChk = mGlobalSearchBarLayout->find<UICheckBox>( "lua_pattern" );
|
||||
luaPatternChk->setTooltipText( kbind.getCommandKeybindString( "toggle-lua-pattern" ) );
|
||||
|
||||
@@ -178,6 +181,7 @@ void GlobalSearchController::initGlobalSearchBar(
|
||||
UIWidget* searchBarClose = mGlobalSearchBarLayout->find<UIWidget>( "global_searchbar_close" );
|
||||
|
||||
caseSensitiveChk->setChecked( globalSearchBarConfig.caseSensitive );
|
||||
regexChk->setChecked( globalSearchBarConfig.regex );
|
||||
luaPatternChk->setChecked( globalSearchBarConfig.luaPattern );
|
||||
wholeWordChk->setChecked( globalSearchBarConfig.wholeWord );
|
||||
escapeSequenceChk->setChecked( globalSearchBarConfig.escapeSequence );
|
||||
@@ -188,24 +192,34 @@ 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] {
|
||||
doGlobalSearch( mGlobalSearchInput->getText(), mGlobalSearchWhereInput->getText(),
|
||||
caseSensitiveChk->isChecked(), wholeWordChk->isChecked(),
|
||||
luaPatternChk->isChecked(), escapeSequenceChk->isChecked(), false );
|
||||
} );
|
||||
mGlobalSearchBarLayout->setCommand(
|
||||
"search-again", [this, caseSensitiveChk, wholeWordChk, luaPatternChk, escapeSequenceChk] {
|
||||
auto listBox = mGlobalSearchHistoryList->getListBox();
|
||||
if ( listBox->getItemSelectedIndex() < mGlobalSearchHistory.size() ) {
|
||||
const auto& item = mGlobalSearchHistory[mGlobalSearchHistory.size() - 1 -
|
||||
listBox->getItemSelectedIndex()];
|
||||
doGlobalSearch( item.search, item.filter, caseSensitiveChk->isChecked(),
|
||||
wholeWordChk->isChecked(), luaPatternChk->isChecked(),
|
||||
escapeSequenceChk->isChecked(),
|
||||
mGlobalSearchTreeReplace == mGlobalSearchTree, true );
|
||||
}
|
||||
"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-again", [this, caseSensitiveChk, wholeWordChk,
|
||||
luaPatternChk, escapeSequenceChk,
|
||||
regexChk] {
|
||||
auto listBox = mGlobalSearchHistoryList->getListBox();
|
||||
if ( listBox->getItemSelectedIndex() < mGlobalSearchHistory.size() ) {
|
||||
const auto& item = mGlobalSearchHistory[mGlobalSearchHistory.size() - 1 -
|
||||
listBox->getItemSelectedIndex()];
|
||||
doGlobalSearch( item.search, item.filter, caseSensitiveChk->isChecked(),
|
||||
wholeWordChk->isChecked(),
|
||||
luaPatternChk->isChecked()
|
||||
? TextDocument::FindReplaceType::LuaPattern
|
||||
: ( regexChk->isChecked() ? TextDocument::FindReplaceType::RegEx
|
||||
: TextDocument::FindReplaceType::Normal ),
|
||||
escapeSequenceChk->isChecked(),
|
||||
mGlobalSearchTreeReplace == mGlobalSearchTree, true );
|
||||
}
|
||||
} );
|
||||
mGlobalSearchBarLayout->setCommand( "search-set-string", [this] {
|
||||
auto listBox = mGlobalSearchHistoryList->getListBox();
|
||||
const auto& item =
|
||||
@@ -232,6 +246,8 @@ void GlobalSearchController::initGlobalSearchBar(
|
||||
mGlobalSearchBarLayout->setCommand( "change-whole-word", [wholeWordChk] {
|
||||
wholeWordChk->setChecked( !wholeWordChk->isChecked() );
|
||||
} );
|
||||
mGlobalSearchBarLayout->setCommand(
|
||||
"toggle-regex", [regexChk] { regexChk->setChecked( !regexChk->isChecked() ); } );
|
||||
mGlobalSearchBarLayout->setCommand( "toggle-lua-pattern", [luaPatternChk] {
|
||||
luaPatternChk->setChecked( !luaPatternChk->isChecked() );
|
||||
} );
|
||||
@@ -248,6 +264,22 @@ void GlobalSearchController::initGlobalSearchBar(
|
||||
mGlobalSearchTree->forceKeyDown( keyEvent );
|
||||
}
|
||||
};
|
||||
|
||||
luaPatternChk->on( Event::OnValueChange, [this, luaPatternChk, regexChk]( const Event* ) {
|
||||
if ( mValueChanging )
|
||||
return;
|
||||
BoolScopedOp op( mValueChanging, true );
|
||||
if ( luaPatternChk->isChecked() && regexChk->isChecked() )
|
||||
regexChk->setChecked( false );
|
||||
} );
|
||||
regexChk->on( Event::OnValueChange, [this, luaPatternChk, regexChk]( const Event* ) {
|
||||
if ( mValueChanging )
|
||||
return;
|
||||
BoolScopedOp op( mValueChanging, true );
|
||||
if ( regexChk->isChecked() && luaPatternChk->isChecked() )
|
||||
luaPatternChk->setChecked( false );
|
||||
} );
|
||||
|
||||
mGlobalSearchInput->setSelectAllDocOnTabNavigate( false );
|
||||
mGlobalSearchWhereInput->setSelectAllDocOnTabNavigate( false );
|
||||
mGlobalSearchInput->on( Event::OnPressEnter, pressEnterCb );
|
||||
@@ -330,28 +362,33 @@ void GlobalSearchController::initGlobalSearchBar(
|
||||
}
|
||||
mGlobalSearchBarLayout->forceKeyDown( *keyEvent );
|
||||
} );
|
||||
mGlobalSearchBarLayout->setCommand(
|
||||
"search-replace-in-files",
|
||||
[this, caseSensitiveChk, wholeWordChk, luaPatternChk, escapeSequenceChk, replaceInput] {
|
||||
if ( mGlobalSearchTreeReplace == mGlobalSearchTree ) {
|
||||
replaceInput->setFocus();
|
||||
replaceInput->getDocument().selectAll();
|
||||
return;
|
||||
}
|
||||
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(), escapeSequenceChk->isChecked(), true );
|
||||
}
|
||||
} );
|
||||
// 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] {
|
||||
auto listBox = mGlobalSearchHistoryList->getListBox();
|
||||
@@ -482,10 +519,12 @@ void GlobalSearchController::clearHistory() {
|
||||
GlobalSearchBarConfig GlobalSearchController::getGlobalSearchBarConfig() const {
|
||||
UICheckBox* caseSensitiveChk = mGlobalSearchBarLayout->find<UICheckBox>( "case_sensitive" );
|
||||
UICheckBox* wholeWordChk = mGlobalSearchBarLayout->find<UICheckBox>( "whole_word" );
|
||||
UICheckBox* regexChk = mGlobalSearchBarLayout->find<UICheckBox>( "regex" );
|
||||
UICheckBox* luaPatternChk = mGlobalSearchBarLayout->find<UICheckBox>( "lua_pattern" );
|
||||
UICheckBox* escapeSequenceChk = mGlobalSearchBarLayout->find<UICheckBox>( "escape_sequence" );
|
||||
GlobalSearchBarConfig globalSeachBarConfig;
|
||||
globalSeachBarConfig.caseSensitive = caseSensitiveChk->isChecked();
|
||||
globalSeachBarConfig.regex = regexChk->isChecked();
|
||||
globalSeachBarConfig.luaPattern = luaPatternChk->isChecked();
|
||||
globalSeachBarConfig.wholeWord = wholeWordChk->isChecked();
|
||||
globalSeachBarConfig.escapeSequence = escapeSequenceChk->isChecked();
|
||||
@@ -599,8 +638,10 @@ std::vector<GlobMatch> GlobalSearchController::parseGlobMatches( const String& s
|
||||
}
|
||||
|
||||
void GlobalSearchController::doGlobalSearch( String text, String filter, bool caseSensitive,
|
||||
bool wholeWord, bool luaPattern, bool escapeSequence,
|
||||
bool searchReplace, bool searchAgain ) {
|
||||
bool wholeWord,
|
||||
TextDocument::FindReplaceType searchType,
|
||||
bool escapeSequence, bool searchReplace,
|
||||
bool searchAgain ) {
|
||||
if ( mApp->getDirTree() && mApp->getDirTree()->getFilesCount() > 0 && !text.empty() ) {
|
||||
mGlobalSearchTree = searchReplace ? mGlobalSearchTreeReplace : mGlobalSearchTreeSearch;
|
||||
mGlobalSearchTreeSearch->setVisible( !searchReplace );
|
||||
@@ -629,15 +670,17 @@ void GlobalSearchController::doGlobalSearch( String text, String filter, bool ca
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
|
||||
mApp->getThreadPool(),
|
||||
#endif
|
||||
[this, clock, search, loader, searchReplace, searchAgain, escapeSequence, luaPattern,
|
||||
[this, clock, search, loader, searchReplace, searchAgain, escapeSequence, searchType,
|
||||
filter]( const ProjectSearch::Result& res ) {
|
||||
Log::info( "Global search for \"%s\" took %.2fms", search.c_str(),
|
||||
clock->getElapsedTime().asMilliseconds() );
|
||||
eeDelete( clock );
|
||||
mUISceneNode->runOnMainThread( [this, loader, res, search, searchReplace,
|
||||
searchAgain, escapeSequence, luaPattern, filter] {
|
||||
searchAgain, escapeSequence, searchType, filter] {
|
||||
auto model = ProjectSearch::asModel( res );
|
||||
model->setResultFromLuaPattern( luaPattern );
|
||||
model->setResultFromLuaPattern( searchType ==
|
||||
TextDocument::FindReplaceType::LuaPattern );
|
||||
model->setResultFromRegEx( searchType == TextDocument::FindReplaceType::RegEx );
|
||||
updateGlobalSearchHistory( model, search, filter, searchReplace, searchAgain,
|
||||
escapeSequence );
|
||||
updateGlobalSearchBarResults( search, model, searchReplace, escapeSequence );
|
||||
@@ -645,10 +688,8 @@ void GlobalSearchController::doGlobalSearch( String text, String filter, bool ca
|
||||
loader->close();
|
||||
} );
|
||||
},
|
||||
caseSensitive, wholeWord,
|
||||
luaPattern ? TextDocument::FindReplaceType::LuaPattern
|
||||
: TextDocument::FindReplaceType::Normal,
|
||||
parseGlobMatches( filter ), mApp->getCurrentProject(), openDocs );
|
||||
caseSensitive, wholeWord, searchType, parseGlobMatches( filter ),
|
||||
mApp->getCurrentProject(), openDocs );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ class GlobalSearchController {
|
||||
{ "escape", "close-global-searchbar" },
|
||||
{ "mod+s", "change-case" },
|
||||
{ "mod+w", "change-whole-word" },
|
||||
{ "mod+p", "toggle-regex" },
|
||||
{ "mod+l", "toggle-lua-pattern" },
|
||||
{ "mod+r", "search-replace-in-files" },
|
||||
{ "mod+g", "search-again" },
|
||||
@@ -48,8 +49,8 @@ class GlobalSearchController {
|
||||
void initGlobalSearchTree( UITreeViewGlobalSearch* searchTree );
|
||||
|
||||
void doGlobalSearch( String text, String filter, bool caseSensitive, bool wholeWord,
|
||||
bool luaPattern, bool escapeSequence, bool searchReplace,
|
||||
bool searchAgain = false );
|
||||
TextDocument::FindReplaceType searchType, bool escapeSequence,
|
||||
bool searchReplace, bool searchAgain = false );
|
||||
|
||||
size_t replaceInFiles( const std::string& replaceText,
|
||||
std::shared_ptr<ProjectSearch::ResultModel> model );
|
||||
@@ -86,6 +87,7 @@ class GlobalSearchController {
|
||||
std::shared_ptr<ProjectSearch::ResultModel> result;
|
||||
};
|
||||
std::deque<SearchHistoryItem> mGlobalSearchHistory;
|
||||
bool mValueChanging{ false };
|
||||
|
||||
void onLoadDone( const Variant& lineNum, const Variant& colNum );
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "projectsearch.hpp"
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/luapattern.hpp>
|
||||
#include <eepp/system/regex.hpp>
|
||||
|
||||
#if EE_PLATFORM == EE_PLATFORM_LINUX
|
||||
// For malloc_trim, which is a GNU extension
|
||||
@@ -142,6 +143,63 @@ searchInFileLuaPattern( const std::string& file, const std::string& text, const
|
||||
return results;
|
||||
}
|
||||
|
||||
static std::vector<ProjectSearch::ResultData::Result> searchInFileRegEx( const std::string& file,
|
||||
const std::string& text,
|
||||
const bool& caseSensitive,
|
||||
const bool& wholeWord ) {
|
||||
std::string fileText;
|
||||
FileSystem::fileGet( file, fileText );
|
||||
RegEx pattern( text );
|
||||
std::vector<ProjectSearch::ResultData::Result> results;
|
||||
Int64 totNl = 0;
|
||||
bool matched = false;
|
||||
Int64 searchRes = 0;
|
||||
std::string fileTextOriginal;
|
||||
|
||||
if ( !caseSensitive ) {
|
||||
fileTextOriginal = fileText;
|
||||
String::toLowerInPlace( fileText );
|
||||
}
|
||||
|
||||
PatternMatcher::Range matches[12];
|
||||
do {
|
||||
int start, end = 0;
|
||||
|
||||
if ( ( matched = pattern.matches( fileText, matches, searchRes ) ) ) {
|
||||
start = matches[0].start;
|
||||
end = matches[0].end;
|
||||
|
||||
if ( wholeWord &&
|
||||
!String::isWholeWord( fileText, fileText.substr( start, end - start ), start ) ) {
|
||||
searchRes = end;
|
||||
continue;
|
||||
}
|
||||
|
||||
Int64 relCol;
|
||||
totNl += countNewLines( fileText, searchRes, start );
|
||||
String str( textLine( caseSensitive ? fileText : fileTextOriginal, start, relCol ) );
|
||||
int len = end - start;
|
||||
ProjectSearch::ResultData::Result res;
|
||||
res.line = std::move( str );
|
||||
res.position = { { totNl, (Int64)relCol }, { totNl, (Int64)( relCol + len ) } };
|
||||
res.start = start;
|
||||
res.end = end;
|
||||
for ( size_t c = 1; c < 12; c++ ) {
|
||||
if ( matches[c].isValid() ) {
|
||||
res.captures.push_back(
|
||||
fileText.substr( matches[c].start, matches[c].end - matches[c].start ) );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
results.emplace_back( std::move( res ) );
|
||||
searchRes = end;
|
||||
}
|
||||
} while ( matched );
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
void ProjectSearch::find( const std::vector<std::string> files, const std::string& string,
|
||||
ResultCb result, bool caseSensitive, bool wholeWord,
|
||||
const TextDocument::FindReplaceType& type,
|
||||
@@ -168,9 +226,12 @@ void ProjectSearch::find( const std::vector<std::string> files, const std::strin
|
||||
if ( skip )
|
||||
continue;
|
||||
|
||||
auto fileRes = type == TextDocument::FindReplaceType::Normal
|
||||
? searchInFileHorspool( file, string, caseSensitive, wholeWord, occ )
|
||||
: searchInFileLuaPattern( file, string, caseSensitive, wholeWord );
|
||||
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 } );
|
||||
}
|
||||
@@ -306,11 +367,14 @@ void ProjectSearch::find( const std::vector<std::string> files, std::string stri
|
||||
} else {
|
||||
pool->run(
|
||||
[findData, file, string, caseSensitive, wholeWord, occ, type] {
|
||||
auto fileRes =
|
||||
type == TextDocument::FindReplaceType::Normal
|
||||
? searchInFileHorspool( file, string, caseSensitive, wholeWord,
|
||||
occ )
|
||||
: searchInFileLuaPattern( file, string, caseSensitive, wholeWord );
|
||||
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() ) {
|
||||
Lock l( findData->resMutex );
|
||||
findData->res.push_back( { std::move( file ), std::move( fileRes ) } );
|
||||
|
||||
@@ -199,10 +199,15 @@ class ProjectSearch {
|
||||
|
||||
bool isResultFromLuaPattern() const { return mResultFromLuaPattern; }
|
||||
|
||||
void setResultFromRegEx( bool ref ) { mResultFromRegEx = ref; }
|
||||
|
||||
bool isResultFromRegEx() const { return mResultFromRegEx; }
|
||||
|
||||
protected:
|
||||
Result mResult;
|
||||
bool mResultFromSymbolReference{ false };
|
||||
bool mResultFromLuaPattern{ false };
|
||||
bool mResultFromRegEx{ false };
|
||||
};
|
||||
|
||||
static std::shared_ptr<ResultModel> asModel( const Result& result ) {
|
||||
|
||||
Reference in New Issue
Block a user