diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index b1fda25ecd56..32dcf2568d21 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1301,6 +1301,9 @@
Search from end to beginning.
+
+ Ignore all comments.
+
Vertical line caret.
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index e328f76545bd..b164300630b5 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -368,6 +368,12 @@ void FindReplaceBar::_update_results_count() {
int col_pos = 0;
+ if (is_ignoring_comments()) {
+ if (line_text.begins_with("#")) {
+ continue;
+ }
+ }
+
while (true) {
col_pos = is_case_sensitive() ? line_text.find(searched, col_pos) : line_text.findn(searched, col_pos);
@@ -427,6 +433,9 @@ bool FindReplaceBar::search_current() {
if (is_case_sensitive()) {
flags |= TextEdit::SEARCH_MATCH_CASE;
}
+ if (is_ignoring_comments()) {
+ flags |= TextEdit::SEARCH_IGNORE_COMMENTS;
+ }
int line, col;
_get_search_from(line, col);
@@ -452,6 +461,9 @@ bool FindReplaceBar::search_prev() {
if (is_case_sensitive()) {
flags |= TextEdit::SEARCH_MATCH_CASE;
}
+ if (is_ignoring_comments()) {
+ flags |= TextEdit::SEARCH_IGNORE_COMMENTS;
+ }
flags |= TextEdit::SEARCH_BACKWARDS;
@@ -487,6 +499,9 @@ bool FindReplaceBar::search_next() {
if (is_case_sensitive()) {
flags |= TextEdit::SEARCH_MATCH_CASE;
}
+ if (is_ignoring_comments()) {
+ flags |= TextEdit::SEARCH_IGNORE_COMMENTS;
+ }
int line, col;
_get_search_from(line, col, true);
@@ -620,6 +635,10 @@ bool FindReplaceBar::is_case_sensitive() const {
return case_sensitive->is_pressed();
}
+bool FindReplaceBar::is_ignoring_comments() const {
+ return ignore_comments->is_pressed();
+}
+
bool FindReplaceBar::is_whole_words() const {
return whole_words->is_pressed();
}
@@ -717,6 +736,12 @@ FindReplaceBar::FindReplaceBar() {
case_sensitive->set_focus_mode(FOCUS_NONE);
case_sensitive->connect("toggled", callable_mp(this, &FindReplaceBar::_search_options_changed));
+ ignore_comments = memnew(CheckBox);
+ hbc_option_search->add_child(ignore_comments);
+ ignore_comments->set_text(TTR("Ignore Comments"));
+ ignore_comments->set_focus_mode(FOCUS_NONE);
+ ignore_comments->connect("toggled", callable_mp(this, &FindReplaceBar::_search_options_changed));
+
whole_words = memnew(CheckBox);
hbc_option_search->add_child(whole_words);
whole_words->set_text(TTR("Whole Words"));
diff --git a/editor/code_editor.h b/editor/code_editor.h
index ded751828751..9650abe13e6f 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -67,6 +67,7 @@ class FindReplaceBar : public HBoxContainer {
Button *find_prev = nullptr;
Button *find_next = nullptr;
CheckBox *case_sensitive = nullptr;
+ CheckBox *ignore_comments = nullptr;
CheckBox *whole_words = nullptr;
TextureButton *hide_button = nullptr;
@@ -121,6 +122,7 @@ class FindReplaceBar : public HBoxContainer {
String get_replace_text() const;
bool is_case_sensitive() const;
+ bool is_ignoring_comments() const;
bool is_whole_words() const;
bool is_selection_only() const;
void set_error(const String &p_label);
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index a0f4ade182e5..e24e7b4fa364 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -54,9 +54,15 @@ inline void pop_back(T &container) {
container.resize(container.size() - 1);
}
-static bool find_next(const String &line, String pattern, int from, bool match_case, bool whole_words, int &out_begin, int &out_end) {
+static bool find_next(const String &line, String pattern, int from, bool match_case, bool ignore_comments, bool whole_words, int &out_begin, int &out_end) {
int end = from;
+ if (ignore_comments) {
+ if (line.begins_with("#")) {
+ return false;
+ }
+ }
+
while (true) {
int begin = match_case ? line.find(pattern, end) : line.findn(pattern, end);
@@ -95,6 +101,10 @@ void FindInFiles::set_match_case(bool p_match_case) {
_match_case = p_match_case;
}
+void FindInFiles::set_ignore_comments(bool p_ignore_comments) {
+ _ignore_comments = p_ignore_comments;
+}
+
void FindInFiles::set_folder(String folder) {
_root_dir = folder;
}
@@ -270,7 +280,7 @@ void FindInFiles::_scan_file(String fpath) {
String line = f->get_line();
- while (find_next(line, _pattern, end, _match_case, _whole_words, begin, end)) {
+ while (find_next(line, _pattern, end, _match_case, _ignore_comments, _whole_words, begin, end)) {
emit_signal(SNAME(SIGNAL_RESULT_FOUND), fpath, line_number, begin, end, line);
}
}
@@ -340,6 +350,10 @@ FindInFilesDialog::FindInFilesDialog() {
_match_case_checkbox->set_text(TTR("Match Case"));
hbc->add_child(_match_case_checkbox);
+ _ignore_comments_checkbox = memnew(CheckBox);
+ _ignore_comments_checkbox->set_text(TTR("Ignore Comments"));
+ hbc->add_child(_ignore_comments_checkbox);
+
gc->add_child(hbc);
}
@@ -430,6 +444,10 @@ String FindInFilesDialog::get_replace_text() const {
return _replace_text_line_edit->get_text();
}
+bool FindInFilesDialog::is_ignoring_comments() const {
+ return _ignore_comments_checkbox->is_pressed();
+}
+
bool FindInFilesDialog::is_match_case() const {
return _match_case_checkbox->is_pressed();
}
@@ -728,6 +746,7 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin
// Trim result item line.
int old_text_size = text.size();
text = text.strip_edges(true, false);
+
int chars_removed = old_text_size - text.size();
String start = vformat("%3s: ", line_number);
@@ -933,7 +952,7 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector
int repl_end = locations[i].end + offset;
int _;
- if (!find_next(line, search_text, repl_begin, _finder->is_match_case(), _finder->is_whole_words(), _, _)) {
+ if (!find_next(line, search_text, repl_begin, _finder->is_match_case(), _finder->is_ignoring_comments(), _finder->is_whole_words(), _, _)) {
// Make sure the replace is still valid in case the file was tampered with.
print_verbose(String("Occurrence no longer matches, replace will be ignored in {0}: line {1}, col {2}").format(varray(fpath, repl_line_number, repl_begin)));
continue;
diff --git a/editor/find_in_files.h b/editor/find_in_files.h
index 46ba3842afae..e3e4d4a1bbd6 100644
--- a/editor/find_in_files.h
+++ b/editor/find_in_files.h
@@ -45,6 +45,7 @@ class FindInFiles : public Node {
void set_search_text(String p_pattern);
void set_whole_words(bool p_whole_word);
void set_match_case(bool p_match_case);
+ void set_ignore_comments(bool p_ignore_comments);
void set_folder(String folder);
void set_filter(const HashSet &exts);
@@ -52,6 +53,7 @@ class FindInFiles : public Node {
bool is_whole_words() const { return _whole_words; }
bool is_match_case() const { return _match_case; }
+ bool is_ignoring_comments() const { return _ignore_comments; }
void start();
void stop();
@@ -76,6 +78,7 @@ class FindInFiles : public Node {
String _root_dir;
bool _whole_words = true;
bool _match_case = true;
+ bool _ignore_comments = true;
// State
bool _searching = false;
@@ -113,6 +116,7 @@ class FindInFilesDialog : public AcceptDialog {
String get_search_text() const;
String get_replace_text() const;
bool is_match_case() const;
+ bool is_ignoring_comments() const;
bool is_whole_words() const;
String get_folder() const;
HashSet get_filter() const;
@@ -139,6 +143,7 @@ class FindInFilesDialog : public AcceptDialog {
LineEdit *_folder_line_edit = nullptr;
CheckBox *_match_case_checkbox = nullptr;
+ CheckBox *_ignore_comments_checkbox = nullptr;
CheckBox *_whole_words_checkbox = nullptr;
Button *_find_button = nullptr;
Button *_replace_button = nullptr;
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 876ef3bae95e..efe4f89864e1 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -3566,6 +3566,7 @@ void ScriptEditor::_start_find_in_files(bool with_replace) {
f->set_search_text(find_in_files_dialog->get_search_text());
f->set_match_case(find_in_files_dialog->is_match_case());
f->set_whole_words(find_in_files_dialog->is_whole_words());
+ f->set_ignore_comments(find_in_files_dialog->is_ignoring_comments());
f->set_folder(find_in_files_dialog->get_folder());
f->set_filter(find_in_files_dialog->get_filter());
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 90974e31dfdf..a5d3ce677c2d 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1130,7 +1130,7 @@ void TextEdit::_notification(int p_what) {
}
if (!clipped && highlight_all_occurrences && !only_whitespaces_highlighted && !highlighted_text.is_empty()) { // Highlight
- int highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
+ int highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS | SEARCH_IGNORE_COMMENTS, 0);
while (highlighted_text_col != -1) {
Vector sel = TS->shaped_text_get_selection(rid, highlighted_text_col + start, highlighted_text_col + highlighted_text.length() + start);
for (int j = 0; j < sel.size(); j++) {
@@ -1147,13 +1147,13 @@ void TextEdit::_notification(int p_what) {
draw_rect(rect, word_highlighted_color);
}
- highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_text_col + 1);
+ highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS | SEARCH_IGNORE_COMMENTS, highlighted_text_col + 1);
}
}
if (!clipped && lookup_symbol_word.length() != 0) { // Highlight word
if (is_ascii_char(lookup_symbol_word[0]) || lookup_symbol_word[0] == '_' || lookup_symbol_word[0] == '.') {
- int highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
+ int highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS | SEARCH_IGNORE_COMMENTS, 0);
while (highlighted_word_col != -1) {
Vector sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + lookup_symbol_word.length() + start);
for (int j = 0; j < sel.size(); j++) {
@@ -1172,7 +1172,7 @@ void TextEdit::_notification(int p_what) {
draw_rect(rect, color);
}
- highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1);
+ highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS | SEARCH_IGNORE_COMMENTS, highlighted_word_col + 1);
}
}
}
@@ -4000,6 +4000,11 @@ Point2i TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_fro
int last_pos = -1;
while (true) {
+ if (p_search_flags & SEARCH_IGNORE_COMMENTS) {
+ if (text_line.begins_with("#")) {
+ break;
+ }
+ }
if (p_search_flags & SEARCH_BACKWARDS) {
while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.rfind(p_key, pos_from) : text_line.rfindn(p_key, pos_from)) != -1) {
if (last_pos <= from_column) {
@@ -5906,6 +5911,7 @@ void TextEdit::_bind_methods() {
BIND_ENUM_CONSTANT(SEARCH_MATCH_CASE);
BIND_ENUM_CONSTANT(SEARCH_WHOLE_WORDS);
BIND_ENUM_CONSTANT(SEARCH_BACKWARDS);
+ BIND_ENUM_CONSTANT(SEARCH_IGNORE_COMMENTS);
ClassDB::bind_method(D_METHOD("set_search_text", "search_text"), &TextEdit::set_search_text);
ClassDB::bind_method(D_METHOD("set_search_flags", "flags"), &TextEdit::set_search_flags);
@@ -6689,6 +6695,10 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc
p_from_column = 0;
}
+ if (p_search_flags & SEARCH_IGNORE_COMMENTS) {
+ return col;
+ }
+
while (col == -1 && p_from_column <= p_search.length()) {
if (p_search_flags & SEARCH_MATCH_CASE) {
col = p_search.find(p_key, p_from_column);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index e4af621b738b..313bed75d6b6 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -116,7 +116,8 @@ class TextEdit : public Control {
enum SearchFlags {
SEARCH_MATCH_CASE = 1,
SEARCH_WHOLE_WORDS = 2,
- SEARCH_BACKWARDS = 4
+ SEARCH_BACKWARDS = 4,
+ SEARCH_IGNORE_COMMENTS = 8
};
private: