Clean up a little bit.

Added options to RegEx.
Fix case insensitive search with RegEx.
Added RegEx to UIDocFindReplace.
This commit is contained in:
Martín Lucas Golini
2024-09-22 21:16:01 -03:00
parent a60cff4d93
commit ffbf3a91d7
9 changed files with 148 additions and 141 deletions
+34 -7
View File
@@ -16,9 +16,9 @@ class EE_API RegExCache {
void setEnabled( bool enabled );
void insert( std::string_view, void* cache );
void insert( std::string_view, Uint32 options, void* cache );
void* find( const std::string_view& );
void* find( const std::string_view&, Uint32 options );
void clear();
@@ -29,7 +29,38 @@ class EE_API RegExCache {
class EE_API RegEx : public PatternMatcher {
public:
RegEx( const std::string_view& pattern, bool useCache = true );
enum Options : Uint32 {
None = 0x00000000u,
AllowEmptyClass = 0x00000001u, // C
AltBsux = 0x00000002u, // C
AutoCallout = 0x00000004u, // C
Caseless = 0x00000008u, // C
DollarEndonly = 0x00000010u, // J M D
Dotall = 0x00000020u, // C
Dupnames = 0x00000040u, // C
Extended = 0x00000080u, // C
Firstline = 0x00000100u, // J M D
MatchUnsetBackref = 0x00000200u, // C J M
Multiline = 0x00000400u, // C
NeverUcp = 0x00000800u, // C
NeverUtf = 0x00001000u, // C
NoAutoCapture = 0x00002000u, // C
NoAutoPossess = 0x00004000u, // C
NoDotstarAnchor = 0x00008000u, // C
NoStartOptimize = 0x00010000u, // J M D
Ucp = 0x00020000u, // C J M D
Ungreedy = 0x00040000u, // C
Utf = 0x00080000u, // C J M D
NeverBackslashC = 0x00100000u, // C
AltCircumflex = 0x00200000u, // J M D
AltVerbnames = 0x00400000u, // C
UseOffsetLimit = 0x00800000u, // J M D
ExtendedMore = 0x01000000u, // C
Literal = 0x02000000u, // C
MatchInvalidUtf = 0x04000000u, // J M D
};
RegEx( const std::string_view& pattern, Options options = Options::Utf, bool useCache = true );
virtual ~RegEx();
@@ -52,10 +83,6 @@ class EE_API RegEx : public PatternMatcher {
int mCaptureCount;
bool mValid{ false };
bool mCached{ false };
RegEx( const std::string_view& pattern, bool useCache, bool init );
void init( const std::string_view& pattern, bool useCache );
};
}} // namespace EE::System
+7 -10
View File
@@ -15,15 +15,11 @@ namespace EE { namespace UI { namespace Tools {
class EE_API UIDocFindReplace : public UILinearLayout, public WidgetCommandExecuter {
public:
static std::unordered_map<std::string, std::string> getDefaultKeybindings() {
return { { "mod+g", "repeat-find" },
{ "escape", "close-find-replace" },
{ "mod+r", "replace-selection" },
{ "mod+shift+n", "find-and-replace" },
{ "mod+shift+r", "replace-all" },
{ "mod+s", "change-case" },
{ "mod+w", "change-whole-word" },
{ "mod+l", "toggle-lua-pattern" },
{ "mod+e", "change-escape-sequence" },
return { { "mod+g", "repeat-find" }, { "escape", "close-find-replace" },
{ "mod+r", "replace-selection" }, { "mod+shift+n", "find-and-replace" },
{ "mod+shift+r", "replace-all" }, { "mod+s", "change-case" },
{ "mod+w", "change-whole-word" }, { "mod+p", "toggle-regex" },
{ "mod+l", "toggle-lua-pattern" }, { "mod+e", "change-escape-sequence" },
{ "mod+shift+g", "find-prev" } };
}
@@ -46,18 +42,19 @@ class EE_API UIDocFindReplace : public UILinearLayout, public WidgetCommandExecu
protected:
bool mReady{ false };
bool mReplaceDisabled{ false };
bool mChangingPattern{ false };
UIWidget* mFindReplaceToggle{ nullptr };
UITextInput* mFindInput{ nullptr };
UITextInput* mReplaceInput{ nullptr };
UISelectButton* mCaseSensitive{ nullptr };
UISelectButton* mLuaPattern{ nullptr };
UISelectButton* mRegEx{ nullptr };
UISelectButton* mWholeWord{ nullptr };
UISelectButton* mEscapeSequences{ nullptr };
UIWidget* mToggle{ nullptr };
UIWidget* mReplaceBox{ nullptr };
std::shared_ptr<Doc::TextDocument> mDoc;
std::vector<std::unique_ptr<UIDataBind<bool>>> mDataBinds;
std::unique_ptr<UIDataBind<TextDocument::FindReplaceType>> mPatternBind;
UIDocFindReplace(
UIWidget* parent, const std::shared_ptr<Doc::TextDocument>& doc,
+2
View File
@@ -151,6 +151,8 @@ template <typename T> class UIDataBind {
std::function<void( const T& newVal )> onValueChangeCb;
const std::set<UIWidget*>& getWidgets() const { return widgets; }
protected:
T* data{ nullptr };
std::set<UIWidget*> widgets;
+14 -21
View File
@@ -9,12 +9,12 @@ RegExCache::~RegExCache() {
clear();
}
void RegExCache::insert( std::string_view key, void* cache ) {
mCache.insert( { String::hash( key ), cache } );
void RegExCache::insert( std::string_view key, Uint32 options, void* cache ) {
mCache.insert( { hashCombine( String::hash( key ), options ), cache } );
}
void* RegExCache::find( const std::string_view& key ) {
auto it = mCache.find( String::hash( key ) );
void* RegExCache::find( const std::string_view& key, Uint32 options ) {
auto it = mCache.find( hashCombine( String::hash( key ), options ) );
return ( it != mCache.end() ) ? it->second : nullptr;
}
@@ -24,32 +24,19 @@ void RegExCache::clear() {
mCache.clear();
}
RegEx::RegEx( const std::string_view& pattern, bool useCache, bool initRegEx ) :
RegEx::RegEx( const std::string_view& pattern, Options options, bool useCache ) :
PatternMatcher( PatternType::PCRE ),
mPattern( pattern ),
mMatchNum( 0 ),
mCompiledPattern( nullptr ),
mCaptureCount( 0 ),
mValid( true ) {
if ( initRegEx )
init( pattern, useCache );
}
RegEx::RegEx( const std::string_view& pattern, bool useCache ) : RegEx( pattern, useCache, true ) {}
RegEx::~RegEx() {
if ( !mCached && mCompiledPattern != nullptr ) {
pcre2_code_free( reinterpret_cast<pcre2_code*>( mCompiledPattern ) );
}
}
void RegEx::init( const std::string_view& pattern, bool useCache ) {
int errornumber;
PCRE2_SIZE erroroffset;
PCRE2_SPTR pattern_sptr = reinterpret_cast<PCRE2_SPTR>( pattern.data() );
if ( useCache && RegExCache::instance()->isEnabled() &&
( mCompiledPattern = RegExCache::instance()->find( pattern ) ) ) {
( mCompiledPattern = RegExCache::instance()->find( pattern, options ) ) ) {
mValid = true;
mCached = true;
return;
@@ -57,7 +44,7 @@ void RegEx::init( const std::string_view& pattern, bool useCache ) {
mCompiledPattern = pcre2_compile( pattern_sptr, // the pattern
pattern.size(), // the length of the pattern
PCRE2_UTF, // default options
options, // default options
&errornumber, // for error number
&erroroffset, // for error offset
NULL // use default compile context
@@ -81,11 +68,17 @@ void RegEx::init( const std::string_view& pattern, bool useCache ) {
// std::to_string( rc ) );
mValid = false;
} else if ( useCache && RegExCache::instance()->isEnabled() ) {
RegExCache::instance()->insert( pattern, mCompiledPattern );
RegExCache::instance()->insert( pattern, options, mCompiledPattern );
mCached = true;
}
}
RegEx::~RegEx() {
if ( !mCached && mCompiledPattern != nullptr ) {
pcre2_code_free( reinterpret_cast<pcre2_code*>( mCompiledPattern ) );
}
}
bool RegEx::matches( const char* stringSearch, int stringStartOffset,
PatternMatcher::Range* matchList, size_t stringLength ) const {
auto* compiledPattern = reinterpret_cast<pcre2_code*>( mCompiledPattern );
+30 -17
View File
@@ -2433,10 +2433,14 @@ struct FindTypeResult {
};
static FindTypeResult findType( const String& str, const String& findStr,
const TextDocument::FindReplaceType& type, int colOffset ) {
const TextDocument::FindReplaceType& type, int colOffset,
bool caseSensitive ) {
switch ( type ) {
case TextDocument::FindReplaceType::RegEx: {
RegEx words( findStr.toUtf8() );
RegEx words( findStr.toUtf8(),
static_cast<RegEx::Options>( RegEx::Options::Utf |
( !caseSensitive ? RegEx::Options::Caseless
: RegEx::Options::None ) ) );
if ( !words.isValid() )
return { String::StringType::npos, String::StringType::npos };
RegEx::Range matches[MAX_CAPTURES];
@@ -2484,11 +2488,15 @@ static FindTypeResult findType( const String& str, const String& findStr,
}
static FindTypeResult findLastType( const String& str, const String& findStr,
const TextDocument::FindReplaceType& type ) {
const TextDocument::FindReplaceType& type,
bool caseSensitive ) {
switch ( type ) {
case TextDocument::FindReplaceType::RegEx: {
// TODO: Implement findLastType for Lua patterns
RegEx words( findStr.toUtf8() );
RegEx words( findStr.toUtf8(),
static_cast<RegEx::Options>( RegEx::Options::Utf |
( !caseSensitive ? RegEx::Options::Caseless
: RegEx::Options::None ) ) );
if ( !words.isValid() )
return { String::StringType::npos, String::StringType::npos };
RegEx::Range matches[MAX_CAPTURES];
@@ -2567,6 +2575,7 @@ TextDocument::SearchResult TextDocument::findText( String text, TextPosition fro
return TextDocument::SearchResult{};
}
bool realCaseSensitive = caseSensitive;
if ( ( type == FindReplaceType::LuaPattern || type == FindReplaceType::RegEx ) &&
caseSensitive == false ) {
caseSensitive =
@@ -2584,24 +2593,26 @@ TextDocument::SearchResult TextDocument::findText( String text, TextPosition fro
from.line() == to.line()
? to.column() - from.column()
: String::InvalidPos ),
text, type, from.column() )
text, type, from.column(), realCaseSensitive )
: findType( String::toLower( line( i ).getText() )
.substr( from.column(), from.line() == to.line()
? to.column() - from.column()
: String::InvalidPos ),
text, type, from.column() );
text, type, from.column(), realCaseSensitive );
if ( String::StringType::npos != col.start ) {
col.start += from.column();
col.end += from.column();
}
} else if ( i == to.line() && to != endOfDoc() ) {
col = caseSensitive
? findType( line( i ).getText().substr( 0, to.column() ), text, type, 0 )
? findType( line( i ).getText().substr( 0, to.column() ), text, type, 0,
realCaseSensitive )
: findType( String::toLower( line( i ).getText() ).substr( 0, to.column() ),
text, type, 0 );
text, type, 0, realCaseSensitive );
} else {
col = caseSensitive ? findType( line( i ).getText(), text, type, 0 )
: findType( String::toLower( line( i ).getText() ), text, type, 0 );
col = caseSensitive ? findType( line( i ).getText(), text, type, 0, realCaseSensitive )
: findType( String::toLower( line( i ).getText() ), text, type, 0,
realCaseSensitive );
}
if ( String::StringType::npos != col.start &&
( !wholeWord || String::isWholeWord( line( i ).getText(), text, col.start ) ) ) {
@@ -2627,6 +2638,7 @@ TextDocument::SearchResult TextDocument::findTextLast( String text, TextPosition
return TextDocument::SearchResult{};
}
bool realCaseSensitive = caseSensitive;
if ( ( type == FindReplaceType::LuaPattern || type == FindReplaceType::RegEx ) &&
caseSensitive == false ) {
caseSensitive =
@@ -2643,24 +2655,25 @@ TextDocument::SearchResult TextDocument::findTextLast( String text, TextPosition
caseSensitive
? findLastType( line( i ).getText().substr(
from.line() == to.line() ? to.column() : 0, from.column() ),
text, type )
text, type, realCaseSensitive )
: findLastType(
String::toLower( line( i ).getText().substr(
from.line() == to.line() ? to.column() : 0, from.column() ) ),
text, type );
text, type, realCaseSensitive );
} else if ( i == to.line() ) {
res = caseSensitive
? findLastType( line( i ).getText().substr( to.column() ), text, type )
? findLastType( line( i ).getText().substr( to.column() ), text, type,
realCaseSensitive )
: findLastType( String::toLower( line( i ).getText().substr( to.column() ) ),
text, type );
text, type, realCaseSensitive );
if ( String::StringType::npos != res.start ) {
res.start += to.column();
res.end += to.column();
}
} else {
res = caseSensitive
? findLastType( line( i ).getText(), text, type )
: findLastType( String::toLower( line( i ).getText() ), text, type );
res = caseSensitive ? findLastType( line( i ).getText(), text, type, realCaseSensitive )
: findLastType( String::toLower( line( i ).getText() ), text, type,
realCaseSensitive );
}
if ( String::StringType::npos != res.start &&
( !wholeWord || String::isWholeWord( line( i ).getText(), text, res.start ) ) ) {
+40 -21
View File
@@ -1,4 +1,5 @@
#include <eepp/scene/actions/actions.hpp>
#include <eepp/system/scopedop.hpp>
#include <eepp/ui/css/stylesheetparser.hpp>
#include <eepp/ui/tools/uidocfindreplace.hpp>
#include <eepp/ui/uiscenenode.hpp>
@@ -80,6 +81,9 @@ const char DOC_FIND_REPLACE_CSS[] = R"css(
.ce_find_replace_box selectbutton.match-case {
icon: url("data:image/svg,<svg fill='#ffffff' width='16' height='16' viewBox='0 0 16 16'><path d='M8.85352 11.7021H7.85449L7.03809 9.54297H3.77246L3.00439 11.7021H2L4.9541 4H5.88867L8.85352 11.7021ZM6.74268 8.73193L5.53418 5.4502C5.49479 5.34277 5.4554 5.1709 5.41602 4.93457H5.39453C5.35872 5.15299 5.31755 5.32487 5.271 5.4502L4.07324 8.73193H6.74268Z'/><path d='M13.756 11.7021H12.8752V10.8428H12.8537C12.4706 11.5016 11.9066 11.8311 11.1618 11.8311C10.6139 11.8311 10.1843 11.686 9.87273 11.396C9.56479 11.106 9.41082 10.721 9.41082 10.2412C9.41082 9.21354 10.016 8.61556 11.2262 8.44727L12.8752 8.21631C12.8752 7.28174 12.4974 6.81445 11.7419 6.81445C11.0794 6.81445 10.4815 7.04004 9.94793 7.49121V6.58887C10.4886 6.24512 11.1117 6.07324 11.8171 6.07324C13.1097 6.07324 13.756 6.75716 13.756 8.125V11.7021ZM12.8752 8.91992L11.5485 9.10254C11.1403 9.15983 10.8324 9.26188 10.6247 9.40869C10.417 9.55192 10.3132 9.80794 10.3132 10.1768C10.3132 10.4453 10.4081 10.6655 10.5978 10.8374C10.7912 11.0057 11.0472 11.0898 11.3659 11.0898C11.8027 11.0898 12.1626 10.9377 12.4455 10.6333C12.7319 10.3254 12.8752 9.93685 12.8752 9.46777V8.91992Z'/></svg>");
}
.ce_find_replace_box selectbutton.luapattern {
icon: url("data:image/svg,<svg width='16' height='16' fill='none'><path d='m 4.8848115,11.097205 a 3.7631475,3.7631475 0 0 0 5.3533025,0 3.840684,3.840684 0 0 0 0,-5.3992983 3.7631475,3.7631475 0 0 0 -5.3533025,0 3.840684,3.840684 0 0 0 0,5.3992983 z m -0.7300257,0.73594 c -1.8819023,-1.8970156 -1.8819023,-4.9741625 0,-6.8711778 a 4.7895202,4.7895202 0 0 1 6.8133542,0 c 1.881245,1.8976724 1.881245,4.9741622 0,6.8711778 a 4.7895202,4.7895202 0 0 1 -6.8140113,0 z M 12.954519,4.5204035 a 1.0263727,1.0263727 0 0 1 -1.460051,0 1.0473995,1.0473995 0 0 1 0,-1.4718788 1.0263727,1.0263727 0 0 1 1.460051,0 1.0473995,1.0473995 0 0 1 0,1.4718788 z' fill='#ffffff' style='stroke-width:0.657089' /><path d='m 10.525919,8.4419094 a 2.0527454,2.0527454 0 0 1 -2.9201028,0 2.0947991,2.0947991 0 0 1 0,-2.9444148 2.0527454,2.0527454 0 0 1 2.9201028,0 2.0947991,2.0947991 0 0 1 0,2.9444148 z M 8.3351847,7.70597 a 1.0263727,1.0263727 0 0 0 1.4600513,0 1.0473995,1.0473995 0 0 0 0,-1.4718789 1.0263727,1.0263727 0 0 0 -1.4600513,0 1.0473995,1.0473995 0 0 0 0,1.4718789 z' fill='#ffffff' style='stroke-width:0.657089' /></svg>");
}
.ce_find_replace_box selectbutton.regex {
icon: url("data:image/svg,<svg fill='#ffffff' width='16' height='16' viewBox='0 0 16 16'><path fill-rule='evenodd' clip-rule='evenodd' d='M10.012 2h.976v3.113l2.56-1.557.486.885L11.47 6l2.564 1.559-.485.885-2.561-1.557V10h-.976V6.887l-2.56 1.557-.486-.885L9.53 6 6.966 4.441l.485-.885 2.561 1.557V2zM2 10h4v4H2v-4z'/></svg>");
}
@@ -107,7 +111,7 @@ const char DOC_FIND_REPLACE_XML[] = R"xml(
<Widget class="expander" layout_width="2dp" layout_height="match_parent" />
<button class="find_replace_toggle" layout_width="16dp" layout_height="wrap_content" padding="2dp" layout_gravity="center" />
<vbox layout_width="wrap_content" layout_height="wrap_content">
<hbox layout_width="320dp" layout_height="wrap_content" paddingRight="1dp" min-width="200dp" clip="border-box">
<hbox layout_width="340dp" layout_height="wrap_content" paddingRight="1dp" min-width="200dp" clip="border-box">
<RelativeLayout layout_width="0dp" layout_weight="1" layout_height="25dp" marginRight="1dp">
<input class="input-find" layout_width="match_parent" layout_height="wrap_content" hint="Find" />
<selectbutton id="ce_find_replace_box-escape-sequences"
@@ -124,7 +128,11 @@ const char DOC_FIND_REPLACE_XML[] = R"xml(
layout_to_left_of="ce_find_replace_box-match-case" marginRight="2dp" />
<selectbutton id="ce_find_replace_box-regex" class="regex" layout_width="wrap_content"
layout_height="wrap_content" layout_gravity="right|center_vertical"
tooltip="@string(lua_pattern_match, Lua Pattern Match)" layout_to_left_of="ce_find_replace_box-whole-word"
tooltip="@string(regex_match, Regular Expression Match)" layout_to_left_of="ce_find_replace_box-whole-word"
marginRight="2dp" />
<selectbutton id="ce_find_replace_box-luapattern" class="luapattern" layout_width="wrap_content"
layout_height="wrap_content" layout_gravity="right|center_vertical"
tooltip="@string(lua_pattern_match, Lua Pattern Match)" layout_to_left_of="ce_find_replace_box-regex"
marginRight="2dp" />
</RelativeLayout>
<button class="prev-button" layout_width="wrap_content" layout_height="24dp" text="Prev." icon="icon(arrow-up, 16dp)" />
@@ -195,7 +203,8 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
bind( "ce_find_replace_box-match-case", mCaseSensitive );
bind( "ce_find_replace_box-escape-sequences", mEscapeSequences );
bind( "ce_find_replace_box-whole-word", mWholeWord );
bind( "ce_find_replace_box-regex", mLuaPattern );
bind( "ce_find_replace_box-luapattern", mLuaPattern );
bind( "ce_find_replace_box-regex", mRegEx );
mFindInput = querySelector<UITextInput>( ".input-find" );
mFindInput->setEscapePastedText( true );
@@ -247,6 +256,10 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
mLuaPattern->setSelected( !mLuaPattern->isSelected() );
refreshHighlight( editor );
} );
setCommand( "toggle-regex", [this, editor] {
mRegEx->setSelected( !mRegEx->isSelected() );
refreshHighlight( editor );
} );
mCaseSensitive->setTooltipText( mCaseSensitive->getTooltipText() + " (" +
getKeyBindings().getCommandKeybindString( "change-case" ) +
@@ -260,7 +273,8 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
mLuaPattern->setTooltipText( mLuaPattern->getTooltipText() + " (" +
getKeyBindings().getCommandKeybindString( "toggle-lua-pattern" ) +
")" );
mRegEx->setTooltipText( mRegEx->getTooltipText() + " (" +
getKeyBindings().getCommandKeybindString( "toggle-regex" ) + ")" );
mReplaceInput = querySelector<UITextInput>( ".input-replace" );
auto addClickListener = [this]( UIWidget* widget, std::string cmd ) {
@@ -292,7 +306,7 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
mFindInput->setSelectAllDocOnTabNavigate( false );
mReplaceInput->setSelectAllDocOnTabNavigate( false );
mFindInput->addEventListener( Event::OnTabNavigate, [this]( const Event* ) {
if ( mReplaceDisabled )
if ( mReplaceDisabled )
return;
if ( !mToggle->hasClass( "enabled" ) ) {
mToggle->addClass( "enabled" );
@@ -308,24 +322,29 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
mDataBinds.emplace_back( UIDataBindBool::New( &mSearchState.wholeWord, mWholeWord ) );
mDataBinds.emplace_back(
UIDataBindBool::New( &mSearchState.escapeSequences, mEscapeSequences ) );
UIDataBind<TextDocument::FindReplaceType>::Converter luaPatternConverter(
[]( const UIDataBind<TextDocument::FindReplaceType>* databind,
TextDocument::FindReplaceType& val, const std::string& str ) -> bool {
val = StyleSheetProperty( databind->getPropertyDefinition(), str ).asBool()
? TextDocument::FindReplaceType::LuaPattern
: TextDocument::FindReplaceType::Normal;
return true;
},
[]( const UIDataBind<TextDocument::FindReplaceType>*, std::string& str,
const TextDocument::FindReplaceType& val ) -> bool {
str = val == TextDocument::FindReplaceType::LuaPattern ? "true" : "false";
return true;
} );
mPatternBind = UIDataBind<TextDocument::FindReplaceType>::New( &mSearchState.type, mLuaPattern,
luaPatternConverter );
mLuaPattern->on( Event::OnValueChange, [this, editor]( const Event* ) {
if ( mChangingPattern )
return;
BoolScopedOp op( mChangingPattern, true );
mSearchState.type = mLuaPattern->isSelected() ? TextDocument::FindReplaceType::LuaPattern
: TextDocument::FindReplaceType::Normal;
mRegEx->setSelected( false );
refreshHighlight( editor );
} );
mRegEx->on( Event::OnValueChange, [this, editor]( const Event* ) {
if ( mChangingPattern )
return;
BoolScopedOp op( mChangingPattern, true );
mSearchState.type = mRegEx->isSelected() ? TextDocument::FindReplaceType::RegEx
: TextDocument::FindReplaceType::Normal;
mLuaPattern->setSelected( false );
refreshHighlight( editor );
} );
auto valueChangeCb = [this, editor]( const auto& ) { refreshHighlight( editor ); };
mPatternBind->onValueChangeCb = valueChangeCb;
for ( const auto& db : mDataBinds )
db->onValueChangeCb = valueChangeCb;
+3 -5
View File
@@ -62,8 +62,8 @@ size_t GlobalSearchController::replaceInFiles( const std::string& replaceText,
}
const ProjectSearch::Result& res = model->getResult();
bool hasCaptures = ( model->isResultFromLuaPattern() || model->isResultFromRegEx() ) &&
LuaPattern::hasMatches( replaceText, "$%d+" );
bool hasCaptures =
model->isResultFromPatternMatch() && LuaPattern::hasMatches( replaceText, "$%d+" );
if ( hasCaptures ) {
for ( const auto& fileResult : res ) {
@@ -678,9 +678,7 @@ void GlobalSearchController::doGlobalSearch( String text, String filter, bool ca
mUISceneNode->runOnMainThread( [this, loader, res, search, searchReplace,
searchAgain, escapeSequence, searchType, filter] {
auto model = ProjectSearch::asModel( res );
model->setResultFromLuaPattern( searchType ==
TextDocument::FindReplaceType::LuaPattern );
model->setResultFromRegEx( searchType == TextDocument::FindReplaceType::RegEx );
model->setOpType( searchType );
updateGlobalSearchHistory( model, search, filter, searchReplace, searchAgain,
escapeSequence );
updateGlobalSearchBarResults( search, model, searchReplace, escapeSequence );
+13 -54
View File
@@ -88,11 +88,10 @@ searchInFileHorspool( const std::string& file, const std::string& text, const bo
}
static std::vector<ProjectSearch::ResultData::Result>
searchInFileLuaPattern( const std::string& file, const std::string& text, const bool& caseSensitive,
const bool& wholeWord ) {
searchInFilePatternMatch( const std::string& file, PatternMatcher& pattern,
const bool& caseSensitive, const bool& wholeWord ) {
std::string fileText;
FileSystem::fileGet( file, fileText );
LuaPattern pattern( text );
std::vector<ProjectSearch::ResultData::Result> results;
Int64 totNl = 0;
bool matched = false;
@@ -143,61 +142,21 @@ searchInFileLuaPattern( const std::string& file, const std::string& text, const
return results;
}
static std::vector<ProjectSearch::ResultData::Result>
searchInFileLuaPattern( const std::string& file, const std::string& text, const bool& caseSensitive,
const bool& wholeWord ) {
LuaPattern pattern( text );
return searchInFilePatternMatch( file, pattern, caseSensitive, wholeWord );
}
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;
RegEx pattern( text, static_cast<RegEx::Options>( RegEx::Options::Utf |
( !caseSensitive ? RegEx::Options::Caseless
: RegEx::Options::None ) ) );
return searchInFilePatternMatch( file, pattern, caseSensitive, wholeWord );
}
void ProjectSearch::find( const std::vector<std::string> files, const std::string& string,
+5 -6
View File
@@ -195,16 +195,15 @@ class ProjectSearch {
bool isResultFromSymbolReference() const { return mResultFromSymbolReference; }
void setResultFromLuaPattern( bool ref ) { mResultFromLuaPattern = ref; }
void setOpType( TextDocument::FindReplaceType opType ) { mOpType = opType; }
bool isResultFromLuaPattern() const { return mResultFromLuaPattern; }
void setResultFromRegEx( bool ref ) { mResultFromRegEx = ref; }
bool isResultFromRegEx() const { return mResultFromRegEx; }
bool isResultFromPatternMatch() const {
return mOpType != TextDocument::FindReplaceType::Normal;
}
protected:
Result mResult;
TextDocument::FindReplaceType mOpType{ TextDocument::FindReplaceType::Normal };
bool mResultFromSymbolReference{ false };
bool mResultFromLuaPattern{ false };
bool mResultFromRegEx{ false };