"Whole Words" search can detect word boundaries inside the search term.

For example, searching for ".func" will now match in "a.func" even with Whole Words enabled.
This commit is contained in:
Brian MacIntosh 2023-10-02 13:30:23 -07:00
parent a2f90d565a
commit 676627e1d1
3 changed files with 21 additions and 7 deletions

View File

@ -368,6 +368,9 @@ void FindReplaceBar::_update_results_count() {
int col_pos = 0; int col_pos = 0;
bool searched_start_is_symbol = is_symbol(searched[0]);
bool searched_end_is_symbol = is_symbol(searched[searched.length() - 1]);
while (true) { while (true) {
col_pos = is_case_sensitive() ? line_text.find(searched, col_pos) : line_text.findn(searched, col_pos); col_pos = is_case_sensitive() ? line_text.find(searched, col_pos) : line_text.findn(searched, col_pos);
@ -376,11 +379,11 @@ void FindReplaceBar::_update_results_count() {
} }
if (is_whole_words()) { if (is_whole_words()) {
if (col_pos > 0 && !is_symbol(line_text[col_pos - 1])) { if (!searched_start_is_symbol && col_pos > 0 && !is_symbol(line_text[col_pos - 1])) {
col_pos += searched.length(); col_pos += searched.length();
continue; continue;
} }
if (col_pos + searched.length() < line_text.length() && !is_symbol(line_text[col_pos + searched.length()])) { if (!searched_end_is_symbol && col_pos + searched.length() < line_text.length() && !is_symbol(line_text[col_pos + searched.length()])) {
col_pos += searched.length(); col_pos += searched.length();
continue; continue;
} }

View File

@ -4112,6 +4112,9 @@ Point2i TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_fro
int line = p_from_line; int line = p_from_line;
int pos = -1; int pos = -1;
bool key_start_is_symbol = is_symbol(p_key[0]);
bool key_end_is_symbol = is_symbol(p_key[p_key.length() - 1]);
for (int i = 0; i < text.size() + 1; i++) { for (int i = 0; i < text.size() + 1; i++) {
if (line < 0) { if (line < 0) {
line = text.size() - 1; line = text.size() - 1;
@ -4175,9 +4178,9 @@ Point2i TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_fro
if (pos != -1 && (p_search_flags & SEARCH_WHOLE_WORDS)) { if (pos != -1 && (p_search_flags & SEARCH_WHOLE_WORDS)) {
// Validate for whole words. // Validate for whole words.
if (pos > 0 && !is_symbol(text_line[pos - 1])) { if (!key_start_is_symbol && pos > 0 && !is_symbol(text_line[pos - 1])) {
is_match = false; is_match = false;
} else if (pos + p_key.length() < text_line.length() && !is_symbol(text_line[pos + p_key.length()])) { } else if (!key_end_is_symbol && pos + p_key.length() < text_line.length() && !is_symbol(text_line[pos + p_key.length()])) {
is_match = false; is_match = false;
} }
} }
@ -7020,6 +7023,9 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc
p_from_column = 0; p_from_column = 0;
} }
bool key_start_is_symbol = is_symbol(p_key[0]);
bool key_end_is_symbol = is_symbol(p_key[p_key.length() - 1]);
while (col == -1 && p_from_column <= p_search.length()) { while (col == -1 && p_from_column <= p_search.length()) {
if (p_search_flags & SEARCH_MATCH_CASE) { if (p_search_flags & SEARCH_MATCH_CASE) {
col = p_search.find(p_key, p_from_column); col = p_search.find(p_key, p_from_column);
@ -7036,9 +7042,9 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc
if (col != -1 && p_search_flags & SEARCH_WHOLE_WORDS) { if (col != -1 && p_search_flags & SEARCH_WHOLE_WORDS) {
p_from_column = col; p_from_column = col;
if (col > 0 && !is_symbol(p_search[col - 1])) { if (!key_start_is_symbol && col > 0 && !is_symbol(p_search[col - 1])) {
col = -1; col = -1;
} else if ((col + p_key.length()) < p_search.length() && !is_symbol(p_search[col + p_key.length()])) { } else if (!key_end_is_symbol && (col + p_key.length()) < p_search.length() && !is_symbol(p_search[col + p_key.length()])) {
col = -1; col = -1;
} }
} }

View File

@ -3193,7 +3193,7 @@ TEST_CASE("[SceneTree][TextEdit] search") {
TextEdit *text_edit = memnew(TextEdit); TextEdit *text_edit = memnew(TextEdit);
SceneTree::get_singleton()->get_root()->add_child(text_edit); SceneTree::get_singleton()->get_root()->add_child(text_edit);
text_edit->set_text("hay needle, hay\nHAY NEEDLE, HAY"); text_edit->set_text("hay needle, hay\nHAY NEEDLE, HAY\nwordword.word.word");
int length = text_edit->get_line(1).length(); int length = text_edit->get_line(1).length();
CHECK(text_edit->search("test", 0, 0, 0) == Point2i(-1, -1)); CHECK(text_edit->search("test", 0, 0, 0) == Point2i(-1, -1));
@ -3225,6 +3225,11 @@ TEST_CASE("[SceneTree][TextEdit] search") {
CHECK(text_edit->search("need", TextEdit::SEARCH_WHOLE_WORDS | TextEdit::SEARCH_MATCH_CASE, 0, 0) == Point2i(-1, -1)); CHECK(text_edit->search("need", TextEdit::SEARCH_WHOLE_WORDS | TextEdit::SEARCH_MATCH_CASE, 0, 0) == Point2i(-1, -1));
CHECK(text_edit->search("need", TextEdit::SEARCH_WHOLE_WORDS | TextEdit::SEARCH_MATCH_CASE | TextEdit::SEARCH_BACKWARDS, 0, 0) == Point2i(-1, -1)); CHECK(text_edit->search("need", TextEdit::SEARCH_WHOLE_WORDS | TextEdit::SEARCH_MATCH_CASE | TextEdit::SEARCH_BACKWARDS, 0, 0) == Point2i(-1, -1));
CHECK(text_edit->search("word", TextEdit::SEARCH_WHOLE_WORDS, 2, 0) == Point2i(9, 2));
CHECK(text_edit->search("word", TextEdit::SEARCH_WHOLE_WORDS, 2, 10) == Point2i(14, 2));
CHECK(text_edit->search(".word", TextEdit::SEARCH_WHOLE_WORDS, 2, 0) == Point2i(8, 2));
CHECK(text_edit->search("word.", TextEdit::SEARCH_WHOLE_WORDS, 2, 0) == Point2i(9, 2));
ERR_PRINT_OFF; ERR_PRINT_OFF;
CHECK(text_edit->search("", 0, 0, 0) == Point2i(-1, -1)); CHECK(text_edit->search("", 0, 0, 0) == Point2i(-1, -1));
CHECK(text_edit->search("needle", 0, -1, 0) == Point2i(-1, -1)); CHECK(text_edit->search("needle", 0, -1, 0) == Point2i(-1, -1));