Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Replace in Files" functionality to text editors (3.x) #55232

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions editor/find_in_files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,17 @@ FindInFilesDialog::FindInFilesDialog() {
_search_text_line_edit->connect("text_entered", this, "_on_search_text_entered");
gc->add_child(_search_text_line_edit);

_replace_label = memnew(Label);
_replace_label->set_text(TTR("Replace:"));
_replace_label->hide();
gc->add_child(_replace_label);

_replace_text_line_edit = memnew(LineEdit);
_replace_text_line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
_replace_text_line_edit->connect("text_entered", this, "_on_replace_text_entered");
_replace_text_line_edit->hide();
gc->add_child(_replace_text_line_edit);

gc->add_child(memnew(Control)); // Space to maintain the grid aligned.

{
Expand Down Expand Up @@ -385,18 +396,49 @@ FindInFilesDialog::FindInFilesDialog() {

Button *cancel_button = get_ok();
cancel_button->set_text(TTR("Cancel"));

_mode = SEARCH_MODE;
}

void FindInFilesDialog::set_search_text(String text) {
_search_text_line_edit->set_text(text);
_on_search_text_modified(text);
}

void FindInFilesDialog::set_replace_text(String text) {
_replace_text_line_edit->set_text(text);
}

void FindInFilesDialog::set_find_in_files_mode(FindInFilesMode p_mode) {
if (_mode == p_mode) {
return;
}

_mode = p_mode;

if (p_mode == SEARCH_MODE) {
set_title(TTR("Find in Files"));
_replace_label->hide();
_replace_text_line_edit->hide();
} else if (p_mode == REPLACE_MODE) {
set_title(TTR("Replace in Files"));
_replace_label->show();
_replace_text_line_edit->show();
}

// After hiding some child controls, recalculate proper dialog size.
set_size(Size2(get_size().x, 0));
}

String FindInFilesDialog::get_search_text() const {
String text = _search_text_line_edit->get_text();
return text.strip_edges();
}

String FindInFilesDialog::get_replace_text() const {
return _replace_text_line_edit->get_text();
}

bool FindInFilesDialog::is_match_case() const {
return _match_case_checkbox->is_pressed();
}
Expand Down Expand Up @@ -473,9 +515,26 @@ void FindInFilesDialog::_on_search_text_modified(String text) {
}

void FindInFilesDialog::_on_search_text_entered(String text) {
// This allows to trigger a global search without leaving the keyboard
// This allows to trigger a global search without leaving the keyboard.
if (!_find_button->is_disabled()) {
custom_action("find");
if (_mode == SEARCH_MODE) {
custom_action("find");
}
}

if (!_replace_button->is_disabled()) {
if (_mode == REPLACE_MODE) {
custom_action("replace");
}
}
}

void FindInFilesDialog::_on_replace_text_entered(String text) {
// This allows to trigger a global search without leaving the keyboard.
if (!_replace_button->is_disabled()) {
if (_mode == REPLACE_MODE) {
custom_action("replace");
}
}
}

Expand All @@ -492,6 +551,7 @@ void FindInFilesDialog::_bind_methods() {
ClassDB::bind_method("_on_folder_selected", &FindInFilesDialog::_on_folder_selected);
ClassDB::bind_method("_on_search_text_modified", &FindInFilesDialog::_on_search_text_modified);
ClassDB::bind_method("_on_search_text_entered", &FindInFilesDialog::_on_search_text_entered);
ClassDB::bind_method("_on_replace_text_entered", &FindInFilesDialog::_on_replace_text_entered);

ADD_SIGNAL(MethodInfo(SIGNAL_FIND_REQUESTED));
ADD_SIGNAL(MethodInfo(SIGNAL_REPLACE_REQUESTED));
Expand Down Expand Up @@ -575,7 +635,7 @@ FindInFilesPanel::FindInFilesPanel() {
_replace_container->add_child(_replace_line_edit);

_replace_all_button = memnew(Button);
_replace_all_button->set_text(TTR("Replace all (no undo)"));
_replace_all_button->set_text(TTR("Replace All (NO UNDO)"));
_replace_all_button->connect("pressed", this, "_on_replace_all_clicked");
_replace_container->add_child(_replace_all_button);

Expand All @@ -602,6 +662,10 @@ void FindInFilesPanel::set_with_replace(bool with_replace) {
}
}

void FindInFilesPanel::set_replace_text(String text) {
_replace_line_edit->set_text(text);
}

void FindInFilesPanel::clear() {
_file_items.clear();
_result_items.clear();
Expand Down Expand Up @@ -906,7 +970,7 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result>
}

String FindInFilesPanel::get_replace_text() {
return _replace_line_edit->get_text().strip_edges();
return _replace_line_edit->get_text();
}

void FindInFilesPanel::update_replace_buttons() {
Expand Down
16 changes: 16 additions & 0 deletions editor/find_in_files.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,23 @@ class FindInFilesDialog : public AcceptDialog {
GDCLASS(FindInFilesDialog, AcceptDialog);

public:
enum FindInFilesMode {
SEARCH_MODE,
REPLACE_MODE
};

static const char *SIGNAL_FIND_REQUESTED;
static const char *SIGNAL_REPLACE_REQUESTED;

FindInFilesDialog();

void set_search_text(String text);
void set_replace_text(String text);

void set_find_in_files_mode(FindInFilesMode p_mode);

String get_search_text() const;
String get_replace_text() const;
bool is_match_case() const;
bool is_whole_words() const;
String get_folder() const;
Expand All @@ -121,8 +130,14 @@ class FindInFilesDialog : public AcceptDialog {
void _on_folder_selected(String path);
void _on_search_text_modified(String text);
void _on_search_text_entered(String text);
void _on_replace_text_entered(String text);

FindInFilesMode _mode;
LineEdit *_search_text_line_edit;

Label *_replace_label;
LineEdit *_replace_text_line_edit;

LineEdit *_folder_line_edit;
CheckBox *_match_case_checkbox;
CheckBox *_whole_words_checkbox;
Expand Down Expand Up @@ -151,6 +166,7 @@ class FindInFilesPanel : public Control {
FindInFiles *get_finder() const { return _finder; }

void set_with_replace(bool with_replace);
void set_replace_text(String text);

void start_search();
void stop_search();
Expand Down
19 changes: 18 additions & 1 deletion editor/plugins/script_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ void ScriptEditorBase::_bind_methods() {
ADD_SIGNAL(MethodInfo("go_to_help", PropertyInfo(Variant::STRING, "what")));
// TODO: This signal is no use for VisualScript.
ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text")));
ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text")));
}

static bool _is_built_in_script(Script *p_script) {
Expand Down Expand Up @@ -1037,6 +1038,9 @@ void ScriptEditor::_menu_option(int p_option) {
case SEARCH_IN_FILES: {
_on_find_in_files_requested("");
} break;
case REPLACE_IN_FILES: {
_on_replace_in_files_requested("");
} break;
case SEARCH_HELP: {
help_search_dialog->popup_dialog();
} break;
Expand Down Expand Up @@ -2132,6 +2136,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
se->connect("go_to_help", this, "_help_class_goto");
se->connect("request_save_history", this, "_save_history");
se->connect("search_in_files_requested", this, "_on_find_in_files_requested");
se->connect("replace_in_files_requested", this, "_on_replace_in_files_requested");

//test for modification, maybe the script was not edited but was loaded

Expand Down Expand Up @@ -2842,10 +2847,12 @@ void ScriptEditor::_update_selected_editor_menu() {
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3), HELP_SEARCH_FIND_PREVIOUS);
script_search_menu->get_popup()->add_separator();
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F), SEARCH_IN_FILES);
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/replace_in_files", TTR("Replace in Files"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R), REPLACE_IN_FILES);
script_search_menu->show();
} else {
if (tab_container->get_child_count() == 0) {
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F), SEARCH_IN_FILES);
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/replace_in_files", TTR("Replace in Files"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R), REPLACE_IN_FILES);
script_search_menu->show();
} else {
script_search_menu->hide();
Expand Down Expand Up @@ -2986,7 +2993,15 @@ void ScriptEditor::_script_changed() {
}

void ScriptEditor::_on_find_in_files_requested(String text) {
find_in_files_dialog->set_find_in_files_mode(FindInFilesDialog::SEARCH_MODE);
find_in_files_dialog->set_search_text(text);
find_in_files_dialog->popup_centered_minsize();
}

void ScriptEditor::_on_replace_in_files_requested(String text) {
find_in_files_dialog->set_find_in_files_mode(FindInFilesDialog::REPLACE_MODE);
find_in_files_dialog->set_search_text(text);
find_in_files_dialog->set_replace_text("");
find_in_files_dialog->popup_centered_minsize();
}

Expand Down Expand Up @@ -3040,6 +3055,7 @@ void ScriptEditor::_start_find_in_files(bool with_replace) {
f->set_filter(find_in_files_dialog->get_filter());

find_in_files->set_with_replace(with_replace);
find_in_files->set_replace_text(find_in_files_dialog->get_replace_text());
find_in_files->start_search();

editor->make_bottom_panel_item_visible(find_in_files);
Expand Down Expand Up @@ -3115,6 +3131,7 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_filter_methods_text_changed", &ScriptEditor::_filter_methods_text_changed);
ClassDB::bind_method("_update_recent_scripts", &ScriptEditor::_update_recent_scripts);
ClassDB::bind_method("_on_find_in_files_requested", &ScriptEditor::_on_find_in_files_requested);
ClassDB::bind_method("_on_replace_in_files_requested", &ScriptEditor::_on_replace_in_files_requested);
ClassDB::bind_method("_start_find_in_files", &ScriptEditor::_start_find_in_files);
ClassDB::bind_method("_on_find_in_files_result_selected", &ScriptEditor::_on_find_in_files_result_selected);
ClassDB::bind_method("_on_find_in_files_modified_files", &ScriptEditor::_on_find_in_files_modified_files);
Expand Down Expand Up @@ -3263,7 +3280,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As...")), FILE_SAVE_AS);
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL);
file_menu->get_popup()->add_separator();
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R), FILE_TOOL_RELOAD_SOFT);
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_R), FILE_TOOL_RELOAD_SOFT);
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH);
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show in FileSystem")), SHOW_IN_FILE_SYSTEM);
file_menu->get_popup()->add_separator();
Expand Down
2 changes: 2 additions & 0 deletions editor/plugins/script_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ class ScriptEditor : public PanelContainer {
DEBUG_KEEP_DEBUGGER_OPEN,
DEBUG_WITH_EXTERNAL_EDITOR,
SEARCH_IN_FILES,
REPLACE_IN_FILES,
SEARCH_HELP,
SEARCH_WEBSITE,
HELP_SEARCH_FIND,
Expand Down Expand Up @@ -399,6 +400,7 @@ class ScriptEditor : public PanelContainer {
Error _save_text_file(Ref<TextFile> p_text_file, const String &p_path);

void _on_find_in_files_requested(String text);
void _on_replace_in_files_requested(String text);
void _on_find_in_files_result_selected(String fpath, int line_number, int begin, int end);
void _start_find_in_files(bool with_replace);
void _on_find_in_files_modified_files(PoolStringArray paths);
Expand Down
7 changes: 7 additions & 0 deletions editor/plugins/script_text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,11 @@ void ScriptTextEditor::_edit_option(int p_op) {
// So this will be delegated to the ScriptEditor.
emit_signal("search_in_files_requested", selected_text);
} break;
case REPLACE_IN_FILES: {
String selected_text = code_editor->get_text_edit()->get_selection_text();

emit_signal("replace_in_files_requested", selected_text);
} break;
case SEARCH_LOCATE_FUNCTION: {
quick_open->popup_dialog(get_functions());
quick_open->set_title(TTR("Go to Function"));
Expand Down Expand Up @@ -1805,6 +1810,7 @@ void ScriptTextEditor::_enable_code_editor() {
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
search_menu->get_popup()->add_separator();
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_in_files"), SEARCH_IN_FILES);
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace_in_files"), REPLACE_IN_FILES);
search_menu->get_popup()->add_separator();
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/contextual_help"), HELP_CONTEXTUAL);
search_menu->get_popup()->connect("id_pressed", this, "_edit_option");
Expand Down Expand Up @@ -2020,6 +2026,7 @@ void ScriptTextEditor::register_editor() {
#endif

ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F);
ED_SHORTCUT("script_text_editor/replace_in_files", TTR("Replace in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R);

#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE);
Expand Down
1 change: 1 addition & 0 deletions editor/plugins/script_text_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ class ScriptTextEditor : public ScriptEditorBase {
SEARCH_LOCATE_FUNCTION,
SEARCH_GOTO_LINE,
SEARCH_IN_FILES,
REPLACE_IN_FILES,
BOOKMARK_TOGGLE,
BOOKMARK_GOTO_NEXT,
BOOKMARK_GOTO_PREV,
Expand Down
6 changes: 6 additions & 0 deletions editor/plugins/text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@ void TextEditor::_edit_option(int p_op) {
// So this will be delegated to the ScriptEditor.
emit_signal("search_in_files_requested", selected_text);
} break;
case REPLACE_IN_FILES: {
String selected_text = code_editor->get_text_edit()->get_selection_text();

emit_signal("replace_in_files_requested", selected_text);
} break;
case SEARCH_GOTO_LINE: {
goto_line_dialog->popup_find_line(tx);
} break;
Expand Down Expand Up @@ -616,6 +621,7 @@ TextEditor::TextEditor() {
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
search_menu->get_popup()->add_separator();
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_in_files"), SEARCH_IN_FILES);
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace_in_files"), REPLACE_IN_FILES);

edit_menu = memnew(MenuButton);
edit_hb->add_child(edit_menu);
Expand Down
1 change: 1 addition & 0 deletions editor/plugins/text_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class TextEditor : public ScriptEditorBase {
SEARCH_FIND_PREV,
SEARCH_REPLACE,
SEARCH_IN_FILES,
REPLACE_IN_FILES,
SEARCH_GOTO_LINE,
BOOKMARK_TOGGLE,
BOOKMARK_GOTO_NEXT,
Expand Down