1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

Add include/exclude to FindInFiles for filtering files.

This commit is contained in:
Daylily-Zeleen
2024-04-12 12:43:23 +08:00
parent 80a3d205f1
commit 1bccf5c9a3
3 changed files with 126 additions and 1 deletions

View File

@@ -103,6 +103,14 @@ void FindInFiles::set_filter(const HashSet<String> &exts) {
_extension_filter = exts; _extension_filter = exts;
} }
void FindInFiles::set_includes(const HashSet<String> &p_include_wildcards) {
_include_wildcards = p_include_wildcards;
}
void FindInFiles::set_excludes(const HashSet<String> &p_exclude_wildcards) {
_exclude_wildcards = p_exclude_wildcards;
}
void FindInFiles::_notification(int p_what) { void FindInFiles::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_PROCESS: { case NOTIFICATION_PROCESS: {
@@ -253,7 +261,16 @@ void FindInFiles::_scan_dir(const String &path, PackedStringArray &out_folders,
} else { } else {
String file_ext = file.get_extension(); String file_ext = file.get_extension();
if (_extension_filter.has(file_ext)) { if (_extension_filter.has(file_ext)) {
out_files_to_scan.push_back(path.path_join(file)); String file_path = path.path_join(file);
bool case_sensitive = dir->is_case_sensitive(path);
if (!_exclude_wildcards.is_empty() && _is_file_matched(_exclude_wildcards, file_path, case_sensitive)) {
continue;
}
if (_include_wildcards.is_empty() || _is_file_matched(_include_wildcards, file_path, case_sensitive)) {
out_files_to_scan.push_back(file_path);
}
} }
} }
} }
@@ -283,6 +300,19 @@ void FindInFiles::_scan_file(const String &fpath) {
} }
} }
bool FindInFiles::_is_file_matched(const HashSet<String> &p_wildcards, const String &p_file_path, bool p_case_sensitive) const {
const String file_path = "/" + p_file_path.replace_char('\\', '/') + "/";
for (const String &wildcard : p_wildcards) {
if (p_case_sensitive && file_path.match(wildcard)) {
return true;
} else if (!p_case_sensitive && file_path.matchn(wildcard)) {
return true;
}
}
return false;
}
void FindInFiles::_bind_methods() { void FindInFiles::_bind_methods() {
ADD_SIGNAL(MethodInfo(SIGNAL_RESULT_FOUND, ADD_SIGNAL(MethodInfo(SIGNAL_RESULT_FOUND,
PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "path"),
@@ -381,9 +411,36 @@ FindInFilesDialog::FindInFilesDialog() {
gc->add_child(hbc); gc->add_child(hbc);
} }
Label *includes_label = memnew(Label);
includes_label->set_text(TTR("Includes:"));
includes_label->set_tooltip_text(TTR("Include the files with the following expressions. Use \",\" to separate."));
includes_label->set_mouse_filter(Control::MOUSE_FILTER_PASS);
gc->add_child(includes_label);
_includes_line_edit = memnew(LineEdit);
_includes_line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
_includes_line_edit->set_placeholder(TTR("example: scripts,scenes/*/test.gd"));
_includes_line_edit->set_accessibility_name(TTRC("Include Files"));
_includes_line_edit->connect(SceneStringName(text_submitted), callable_mp(this, &FindInFilesDialog::_on_search_text_submitted));
gc->add_child(_includes_line_edit);
Label *excludes_label = memnew(Label);
excludes_label->set_text(TTR("Excludes:"));
excludes_label->set_tooltip_text(TTR("Exclude the files with the following expressions. Use \",\" to separate."));
excludes_label->set_mouse_filter(Control::MOUSE_FILTER_PASS);
gc->add_child(excludes_label);
_excludes_line_edit = memnew(LineEdit);
_excludes_line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
_excludes_line_edit->set_placeholder(TTR("example: res://addons,scenes/test/*.gd"));
_excludes_line_edit->set_accessibility_name(TTRC("Exclude Files"));
_excludes_line_edit->connect(SceneStringName(text_submitted), callable_mp(this, &FindInFilesDialog::_on_search_text_submitted));
gc->add_child(_excludes_line_edit);
Label *filter_label = memnew(Label); Label *filter_label = memnew(Label);
filter_label->set_text(TTR("Filters:")); filter_label->set_text(TTR("Filters:"));
filter_label->set_tooltip_text(TTR("Include the files with the following extensions. Add or remove them in ProjectSettings.")); filter_label->set_tooltip_text(TTR("Include the files with the following extensions. Add or remove them in ProjectSettings."));
filter_label->set_mouse_filter(Control::MOUSE_FILTER_PASS);
gc->add_child(filter_label); gc->add_child(filter_label);
_filters_container = memnew(HBoxContainer); _filters_container = memnew(HBoxContainer);
@@ -480,6 +537,36 @@ HashSet<String> FindInFilesDialog::get_filter() const {
return filters; return filters;
} }
HashSet<String> FindInFilesDialog::get_includes() const {
HashSet<String> includes;
String text = _includes_line_edit->get_text();
if (text.is_empty()) {
return includes;
}
PackedStringArray wildcards = text.split(",", false);
for (const String &wildcard : wildcards) {
includes.insert(validate_filter_wildcard(wildcard));
}
return includes;
}
HashSet<String> FindInFilesDialog::get_excludes() const {
HashSet<String> excludes;
String text = _excludes_line_edit->get_text();
if (text.is_empty()) {
return excludes;
}
PackedStringArray wildcards = text.split(",", false);
for (const String &wildcard : wildcards) {
excludes.insert(validate_filter_wildcard(wildcard));
}
return excludes;
}
void FindInFilesDialog::_notification(int p_what) { void FindInFilesDialog::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: { case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -562,6 +649,29 @@ void FindInFilesDialog::_on_folder_selected(String path) {
_folder_line_edit->set_text(path); _folder_line_edit->set_text(path);
} }
String FindInFilesDialog::validate_filter_wildcard(const String &p_expression) const {
String ret = p_expression.replace_char('\\', '/');
if (ret.begins_with("./")) {
// Relative to the project root.
ret = "res://" + ret.trim_prefix("./");
}
if (ret.begins_with(".")) {
// To match extension.
ret = "*" + ret;
}
if (!ret.begins_with("*")) {
ret = "*/" + ret.trim_prefix("/");
}
if (!ret.ends_with("*")) {
ret = ret.trim_suffix("/") + "/*";
}
return ret;
}
void FindInFilesDialog::_bind_methods() { void FindInFilesDialog::_bind_methods() {
ADD_SIGNAL(MethodInfo(SIGNAL_FIND_REQUESTED)); ADD_SIGNAL(MethodInfo(SIGNAL_FIND_REQUESTED));
ADD_SIGNAL(MethodInfo(SIGNAL_REPLACE_REQUESTED)); ADD_SIGNAL(MethodInfo(SIGNAL_REPLACE_REQUESTED));

View File

@@ -46,6 +46,8 @@ public:
void set_match_case(bool p_match_case); void set_match_case(bool p_match_case);
void set_folder(const String &folder); void set_folder(const String &folder);
void set_filter(const HashSet<String> &exts); void set_filter(const HashSet<String> &exts);
void set_includes(const HashSet<String> &p_include_wildcards);
void set_excludes(const HashSet<String> &p_exclude_wildcards);
String get_search_text() const { return _pattern; } String get_search_text() const { return _pattern; }
@@ -69,9 +71,13 @@ private:
void _scan_dir(const String &path, PackedStringArray &out_folders, PackedStringArray &out_files_to_scan); void _scan_dir(const String &path, PackedStringArray &out_folders, PackedStringArray &out_files_to_scan);
void _scan_file(const String &fpath); void _scan_file(const String &fpath);
bool _is_file_matched(const HashSet<String> &p_wildcards, const String &p_file_path, bool p_case_sensitive) const;
// Config // Config
String _pattern; String _pattern;
HashSet<String> _extension_filter; HashSet<String> _extension_filter;
HashSet<String> _include_wildcards;
HashSet<String> _exclude_wildcards;
String _root_dir; String _root_dir;
bool _whole_words = true; bool _whole_words = true;
bool _match_case = true; bool _match_case = true;
@@ -115,6 +121,8 @@ public:
bool is_whole_words() const; bool is_whole_words() const;
String get_folder() const; String get_folder() const;
HashSet<String> get_filter() const; HashSet<String> get_filter() const;
HashSet<String> get_includes() const;
HashSet<String> get_excludes() const;
protected: protected:
void _notification(int p_what); void _notification(int p_what);
@@ -130,6 +138,8 @@ private:
void _on_search_text_submitted(const String &text); void _on_search_text_submitted(const String &text);
void _on_replace_text_submitted(const String &text); void _on_replace_text_submitted(const String &text);
String validate_filter_wildcard(const String &p_expression) const;
FindInFilesMode _mode; FindInFilesMode _mode;
LineEdit *_search_text_line_edit = nullptr; LineEdit *_search_text_line_edit = nullptr;
@@ -143,6 +153,9 @@ private:
Button *_replace_button = nullptr; Button *_replace_button = nullptr;
FileDialog *_folder_dialog = nullptr; FileDialog *_folder_dialog = nullptr;
HBoxContainer *_filters_container = nullptr; HBoxContainer *_filters_container = nullptr;
LineEdit *_includes_line_edit = nullptr;
LineEdit *_excludes_line_edit = nullptr;
HashMap<String, bool> _filters_preferences; HashMap<String, bool> _filters_preferences;
}; };

View File

@@ -4035,6 +4035,8 @@ void ScriptEditor::_start_find_in_files(bool with_replace) {
f->set_whole_words(find_in_files_dialog->is_whole_words()); f->set_whole_words(find_in_files_dialog->is_whole_words());
f->set_folder(find_in_files_dialog->get_folder()); f->set_folder(find_in_files_dialog->get_folder());
f->set_filter(find_in_files_dialog->get_filter()); f->set_filter(find_in_files_dialog->get_filter());
f->set_includes(find_in_files_dialog->get_includes());
f->set_excludes(find_in_files_dialog->get_excludes());
find_in_files->set_with_replace(with_replace); find_in_files->set_with_replace(with_replace);
find_in_files->set_replace_text(find_in_files_dialog->get_replace_text()); find_in_files->set_replace_text(find_in_files_dialog->get_replace_text());