diff --git a/src/text_editor/view.cpp b/src/text_editor/view.cpp index df5250e..39e7ccf 100644 --- a/src/text_editor/view.cpp +++ b/src/text_editor/view.cpp @@ -676,7 +676,7 @@ void EncloseLine(View *view) { } } -void SelectAllOccurences(View *view, String16 needle) { +bool SelectAllOccurences(View *view, String16 needle) { Buffer *buffer = GetBuffer(view->active_buffer); Scratch scratch; Array all = FindAll(scratch, buffer, needle); @@ -686,5 +686,7 @@ void SelectAllOccurences(View *view, String16 needle) { Add(&view->carets, it); } MergeCarets(buffer, &view->carets); + return true; } + return false; } diff --git a/src/text_editor/window_command.cpp b/src/text_editor/window_command.cpp index 953bc2a..2ee8c74 100644 --- a/src/text_editor/window_command.cpp +++ b/src/text_editor/window_command.cpp @@ -206,27 +206,95 @@ void Coro_SearchProject(mco_coro *co) { } } -void CMD_ReplaceAll() { +void Coro_ReplaceAll(mco_coro *co) { BSet main = GetBSet(PrimaryWindowID); String16 string = FetchLoadWord(main.view); - Scratch scratch; - Array parts = Split(scratch, string, u"@>"); - if (parts.len != 2) { - ReportErrorf("Invalid ReplaceAll pattern"); - return; + String string8 = ToString(CoCurr->arena, string); + String16 needle = {}; + String16 replace = {}; + + { + JumpTempBuffer(&main); + NextActiveWindowID = main.window->id; + RawAppendf(main.buffer, ":Submit (enter) :Cancel (escape)\nString to search for::%S", string8); + + Caret field_seek = FindNext(main.buffer, u"for::", MakeCaret(0)); + main.view->carets[0] = FindNext(main.buffer, string, field_seek); + AddHook(&main.view->hooks, "Submit", "enter", [](){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Submit";}); + AddHook(&main.view->hooks, "Cancel", "escape", [](){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Cancel";}); + + String result = "Cancel"; + for (;;) { + if (main.window->active_view != main.view->id || (main.window->id != PrimaryWindowID && main.window->id != ActiveWindowID) || main.window->close) { + break; + } + + if (main.view->hook_cmd != "") { + result = main.view->hook_cmd; + break; + } + + CoYield(co); + } + Close(main.buffer->id); + if (result == "Cancel") { + return; + } + + field_seek = FindNext(main.buffer, u"for::", MakeCaret(0)); + Range range = {field_seek.range.max, main.buffer->len}; + needle = GetString(main.buffer, range); + } + + { + JumpTempBuffer(&main); + NextActiveWindowID = main.window->id; + RawAppendf(main.buffer, ":Submit (enter) :Cancel (escape)\nString to replace with::%S", string8); + + Caret field_seek = FindNext(main.buffer, u"with::", MakeCaret(0)); + main.view->carets[0] = FindNext(main.buffer, string, field_seek); + AddHook(&main.view->hooks, "Submit", "enter", [](){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Submit";}); + AddHook(&main.view->hooks, "Cancel", "escape", [](){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Cancel";}); + String result = "Cancel"; + for (;;) { + if (main.window->active_view != main.view->id || (main.window->id != PrimaryWindowID && main.window->id != ActiveWindowID) || main.window->close) { + break; + } + + if (main.view->hook_cmd != "") { + result = main.view->hook_cmd; + break; + } + + CoYield(co); + } + Close(main.buffer->id); + + if (result == "Cancel") { + return; + } + + field_seek = FindNext(main.buffer, u"with::", MakeCaret(0)); + Range range = {field_seek.range.max, main.buffer->len}; + replace = GetString(main.buffer, range); } - String16 needle = parts[0]; - String16 replace = parts[1]; ForItem (buffer, Buffers) { if (buffer->special || buffer->is_dir || buffer->temp || buffer->dont_try_to_save_in_bulk_ops) { continue; } View *view = OpenBufferView(buffer->name); - SelectAllOccurences(view, needle); - Replace(view, replace); + if (SelectAllOccurences(view, needle)) { + Replace(view, replace); + } } +} + +void CMD_ReplaceAll() { + CoRemove("Coro_ReplaceAll"); + CoData *data = CoAdd(Coro_ReplaceAll); + CoResume(data); } RegisterCommand(CMD_ReplaceAll, "", "Search and replace over the entire project, you need to select a text with format like this 'FindAnd@>ReplaceWith' and executing the command will change all occurences of FindAnd to ReplaceWith"); void FuzzySearchViewUpdate() {