diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index c97ee6a..55fd3ba 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -1477,3 +1477,152 @@ void CMD_ClearCarets(HookParam param) { } } } RegisterCommand(CMD_ClearCarets, "escape", "Clear all carets and reset to 1 caret, also do some windowing stuff that closes things on escape"); + +void Coro_ReplaceAll(mco_coro *co) { + BSet main = GetBSet(PrimaryWindowID); + String16 string = FetchLoadWord(main.view); + 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); + AddCommand(&main.view->hooks, "Submit", "enter", [](HookParam param){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Submit";}); + AddCommand(&main.view->hooks, "Cancel", "escape", [](HookParam param){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", ToString(CoCurr->arena, needle)); + + Caret field_seek = FindNext(main.buffer, u"with::", MakeCaret(0)); + main.view->carets[0] = MakeCaret(main.buffer->len, field_seek.range.max); + AddCommand(&main.view->hooks, "Submit", "enter", [](HookParam param){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Submit";}); + AddCommand(&main.view->hooks, "Cancel", "escape", [](HookParam param){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); + } + + 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); + if (SelectAllOccurences(view, needle)) { + Replace(view, replace); + } + } +} + +void CMD_ReplaceAll(HookParam param) { + CoRemove("Coro_ReplaceAll"); + CoData *data = CoAdd(Coro_ReplaceAll); + CoResume(data); +} RegisterCommand(CMD_ReplaceAll, "ctrl-shift-r", "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 UpdateSearchProjectView(HookParam param) { + Scratch scratch; + BSet active = GetBSet(ActiveWindowID); + String16 line_string = GetLineStringWithoutNL(active.buffer, 0); + uint64_t hash = HashBytes(line_string.data, line_string.len * sizeof(char16_t)); + if (active.view->prev_search_line_hash != hash) { + active.view->prev_search_line_hash = hash; + if (line_string.len > 0) { + // @todo: do we reintroduce history here? like in fuzzy search view + Caret caret = active.view->carets[0]; + SelectEntireBuffer(active.view); + Replace(active.view, line_string); + Append(active.view, "\n", false); + + CoRemove("Coro_SearchProject"); + CoData *dat = CoAdd(Coro_SearchProject); + SearchProjectParams *param = AllocType(dat->arena, SearchProjectParams); + param->needle = Copy16(dat->arena, line_string); + param->buffer = active.buffer->id; + dat->user_ctx = param; + dat->dont_wait_until_resolved = true; + CoResume(dat); + + active.view->carets[0] = caret; + } + } +} + +void CMD_SearchProject(HookParam param) { + BSet main = GetBSet(PrimaryWindowID); + String16 string = {}; + if (main.view->carets.len == 1 && GetSize(main.view->carets[0]) > 0) { + string = GetString(main.buffer, main.view->carets[0].range); + } + + NextActiveWindowID = main.window->id; + Buffer *search_project_buffer = GetBuffer(SearchProjectBufferID); + View *view = WindowOpenBufferView(main.window, search_project_buffer->name); + view->special = true; + view->kind = ViewKind_ActiveSearch; + AddCommand(&view->hooks, "Open", "ctrl-q | enter | f12", [](HookParam param) { + BSet active = GetBSet(ActiveWindowID); + BSet main = GetBSet(PrimaryWindowID); + NextActiveWindowID = main.window->id; + String16 string = FetchFuzzyViewLoadLine(active.view); + main.window->active_goto_list = active.view->id; + main.window->goto_list_pos = active.view->carets[0].range.min; + Open(string); + }); + AddHook(&view->hooks, HookKind_AppUpdate, "UpdateSearchProjectView", "", UpdateSearchProjectView); + SelectRange(view, GetLineRangeWithoutNL(search_project_buffer, 0)); + if (string.len) { + Replace(view, string); + SelectEntireBuffer(view); + } +} RegisterCommand(CMD_SearchProject, "ctrl-shift-f", "Interactive search over the entire project in a new buffer view"); diff --git a/src/text_editor/process.cpp b/src/text_editor/process.cpp index 7cbbb4d..b7a9e4a 100644 --- a/src/text_editor/process.cpp +++ b/src/text_editor/process.cpp @@ -4,8 +4,7 @@ // the appropriate handles. This happens in this case when git grep calls // 'less' program which errors out and doesn't print anything // @todo: maybe I should ask someone smarter about this! -void UpdateProcesses() { - ProfileFunction(); +void UpdateProcesses(HookParam param) { IterRemove(ActiveProcesses) { IterRemovePrepare(ActiveProcesses); Scratch scratch; @@ -20,12 +19,12 @@ void UpdateProcesses() { remove_item = true; } } -} +} RegisterHook(UpdateProcesses, HookKind_AppUpdate, "", "Polls all the processes and outputs the results to corresponding views"); void Exec(ViewID view, bool scroll_to_end, String cmd, String working_dir) { - Process process = SpawnProcess(cmd, working_dir, {}, ProcessEnviroment); + Process process = SpawnProcess(cmd, working_dir, {}, ProcessEnviroment); ReportDebugf("process %lld start. is_valid = %d cmd = %S working_dir = %S", process.id, process.is_valid, cmd, working_dir); - process.view_id = view.id; + process.view_id = view.id; process.scroll_to_end = scroll_to_end; if (process.is_valid) Add(&ActiveProcesses, process); } diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 7ce8a6c..940c121 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -20,9 +20,9 @@ #include "buffer.cpp" #include "view.cpp" #include "window.cpp" +#include "window_status.cpp" #include "window_command.cpp" #include "window_debug.cpp" -#include "window_status.cpp" #include "window_search.cpp" #include "window_build.cpp" #include "process.cpp" @@ -583,15 +583,23 @@ void Update(Event event) { OnCommand(event); - For (GlobalHooks) { - if (it.kind == HookKind_AppUpdate) { - ProfileScopeEx(it.name); - it.function(HookParam{}); + { + BSet set = GetBSet(ActiveWindowID); + For (set.view->hooks) { + if (it.kind == HookKind_AppUpdate) { + ProfileScopeEx(it.name); + it.function(HookParam{}); + } + } + + For (GlobalHooks) { + if (it.kind == HookKind_AppUpdate) { + ProfileScopeEx(it.name); + it.function(HookParam{}); + } } } - FuzzySearchViewUpdate(); - UpdateProcesses(); CoUpdate(&event); For(IterateInReverse(&order)) { @@ -886,7 +894,7 @@ int main(int argc, char **argv) InitBuffers(); InitRender(); ReloadFont(PathToFont, (U32)FontSize); - InitWindows(); + CreateWind(); InitOS(ReportWarningf); For (GlobalHooks) { diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index 8cc673b..774b284 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -369,8 +369,6 @@ BSet Open(String16 path, ResolveOpenMeta meta = ResolveOpenMeta_Normal); void CenterView(WindowID window); void TrimWhitespace(Buffer *buffer, bool trim_lines_with_caret = false); void JumpTempBuffer(BSet *set, String buffer_name = ""); -void CommandWindowLayout(Rect2I *rect, Int wx, Int wy); -void CommandWindowInit(); View *FindView(BufferID buffer_id, View *default_view = NULL); bool operator==(BufferID a, BufferID b) { return a.id == b.id; } diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index 663291a..fd0acfa 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -114,11 +114,6 @@ View *WindowOpenBufferView(Window *new_parent_window, String name) { return result; } -void InitWindows() { - CreateWind(); - CommandWindowInit(); -} - void CalcNiceties(Window *n) { float scrollbar_size = (10.f * DPIScale); float line_numbers_size = (float)n->font->char_spacing * 10.f; @@ -157,8 +152,6 @@ void LayoutWindows(int16_t wx, int16_t wy) { } } - CommandWindowLayout(&screen_rect, wx, wy); - // Column layout Int c = 0; double size = WindowCalcEvenResizerValue(wx, &c); diff --git a/src/text_editor/window_command.cpp b/src/text_editor/window_command.cpp index 3b4dc90..ceccd55 100644 --- a/src/text_editor/window_command.cpp +++ b/src/text_editor/window_command.cpp @@ -71,26 +71,41 @@ void OpenCommand(BSet active) { Open(string); } -void CMD_CommandWindowOpen(HookParam param) { - BSet active = GetBSet(ActiveWindowID); - BSet main = GetBSet(PrimaryWindowID); - NextActiveWindowID = main.window->id; - String16 string = FetchFuzzyViewLoadLine(active.view); - if (active.view->kind == ViewKind_ActiveSearch) { - main.window->active_goto_list = active.view->id; - main.window->goto_list_pos = active.view->carets[0].range.min; - } - Open(string); -} +struct SearchProjectParams { + String16 needle; + BufferID buffer; +}; -void CommandWindowLayout(Rect2I *rect, Int wx, Int wy) { - Window *n = GetWindow(CommandWindowID); - Rect2I copy_rect = *rect; - if (!n->visible) { - rect = ©_rect; +void Coro_SearchProject(mco_coro *co) { + SearchProjectParams *param = (SearchProjectParams *)CoCurr->user_ctx; + + Array buffers = {CoCurr->arena}; + For (Buffers) { + Add(&buffers, it->id); + } + + ForItem (id, buffers) { + Buffer *it = GetBuffer(id, NULL); + if (it == NULL || it->special || it->is_dir || it->temp || it->dont_try_to_save_in_bulk_ops) { + continue; + } + + { + Scratch scratch; + Array occurences = FindAll(scratch, it, param->needle); + Buffer *out_buffer = GetBuffer(param->buffer); + ForItem (caret, occurences) { + Int pos = caret.range.min; + Int line = PosToLine(it, pos); + Range range = GetLineRangeWithoutNL(it, line); + Int column = pos - range.min; + String16 line_string = GetString(it, range); + String line_string8 = ToString(scratch, line_string); + RawAppendf(out_buffer, "%S ||> %S:%lld:%lld\n", line_string8, it->name, (long long)line + 1, (long long)column + 1); + } + } + CoYield(co); } - Int barsize = Clamp((Int)n->font->line_spacing*10, (Int)0, (Int)wx - 100); - n->document_rect = n->total_rect = CutBottom(rect, barsize); } float NewFuzzyRate(String16 s, String16 p) { @@ -167,214 +182,55 @@ Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_ return ratings; } -struct SearchProjectParams { - String16 needle; - BufferID buffer; -}; - -void Coro_SearchProject(mco_coro *co) { - SearchProjectParams *param = (SearchProjectParams *)CoCurr->user_ctx; - - Array buffers = {CoCurr->arena}; - For (Buffers) { - Add(&buffers, it->id); - } - - ForItem (id, buffers) { - Buffer *it = GetBuffer(id, NULL); - if (it == NULL || it->special || it->is_dir || it->temp || it->dont_try_to_save_in_bulk_ops) { - continue; - } - - { - Scratch scratch; - Array occurences = FindAll(scratch, it, param->needle); - Buffer *out_buffer = GetBuffer(param->buffer); - ForItem (caret, occurences) { - Int pos = caret.range.min; - Int line = PosToLine(it, pos); - Range range = GetLineRangeWithoutNL(it, line); - Int column = pos - range.min; - String16 line_string = GetString(it, range); - String line_string8 = ToString(scratch, line_string); - RawAppendf(out_buffer, "%S ||> %S:%lld:%lld\n", line_string8, it->name, (long long)line + 1, (long long)column + 1); - } - } - CoYield(co); - } -} - -void Coro_ReplaceAll(mco_coro *co) { - BSet main = GetBSet(PrimaryWindowID); - String16 string = FetchLoadWord(main.view); - 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); - AddCommand(&main.view->hooks, "Submit", "enter", [](HookParam param){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Submit";}); - AddCommand(&main.view->hooks, "Cancel", "escape", [](HookParam param){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", ToString(CoCurr->arena, needle)); - - Caret field_seek = FindNext(main.buffer, u"with::", MakeCaret(0)); - main.view->carets[0] = MakeCaret(main.buffer->len, field_seek.range.max); - AddCommand(&main.view->hooks, "Submit", "enter", [](HookParam param){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Submit";}); - AddCommand(&main.view->hooks, "Cancel", "escape", [](HookParam param){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); - } - - 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); - if (SelectAllOccurences(view, needle)) { - Replace(view, replace); - } - } -} - -void CMD_ReplaceAll(HookParam param) { - CoRemove("Coro_ReplaceAll"); - CoData *data = CoAdd(Coro_ReplaceAll); - CoResume(data); -} RegisterCommand(CMD_ReplaceAll, "ctrl-shift-r", "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() { - ProfileFunction(); +void UpdateFuzzySearchView(HookParam param) { + Scratch scratch; BSet active = GetBSet(ActiveWindowID); - if (active.view->kind == ViewKind_ActiveSearch) { - Scratch scratch; - String16 line_string = GetLineStringWithoutNL(active.buffer, 0); - uint64_t hash = HashBytes(line_string.data, line_string.len * sizeof(char16_t)); - if (active.view->prev_search_line_hash != hash) { - active.view->prev_search_line_hash = hash; - if (line_string.len > 0) { - // @todo: do we reintroduce history here? - Caret caret = active.view->carets[0]; - SelectEntireBuffer(active.view); - Replace(active.view, line_string); - Append(active.view, "\n", false); + String16 line_string = GetLineStringWithoutNL(active.buffer, 0); + uint64_t hash = HashBytes(line_string.data, line_string.len * sizeof(char16_t)); + if (active.view->prev_search_line_hash != hash) { + active.view->prev_search_line_hash = hash; + Array ratings = FuzzySearchLines(scratch, active.buffer, 1, active.buffer->line_starts.len, line_string); - CoRemove("Coro_SearchProject"); - CoData *dat = CoAdd(Coro_SearchProject); - SearchProjectParams *param = AllocType(dat->arena, SearchProjectParams); - param->needle = Copy16(dat->arena, line_string); - param->buffer = active.buffer->id; - dat->user_ctx = param; - dat->dont_wait_until_resolved = true; - CoResume(dat); - - active.view->carets[0] = caret; - } + Buffer *scratch_buff = CreateScratchBuffer(scratch, active.buffer->cap); + RawAppend(scratch_buff, line_string); + For(IterateInReverse(&ratings)) { + String16 s = GetLineStringWithoutNL(active.buffer, it.index); + if (s.len == 0) continue; + RawAppend(scratch_buff, u"\n"); + RawAppend(scratch_buff, s); } - } else if (active.view->kind == ViewKind_FuzzySearch) { - Scratch scratch; - String16 line_string = GetLineStringWithoutNL(active.buffer, 0); - uint64_t hash = HashBytes(line_string.data, line_string.len * sizeof(char16_t)); - if (active.view->prev_search_line_hash != hash) { - active.view->prev_search_line_hash = hash; - Array ratings = FuzzySearchLines(scratch, active.buffer, 1, active.buffer->line_starts.len, line_string); - Buffer *scratch_buff = CreateScratchBuffer(scratch, active.buffer->cap); - RawAppend(scratch_buff, line_string); - For(IterateInReverse(&ratings)) { - String16 s = GetLineStringWithoutNL(active.buffer, it.index); - if (s.len == 0) continue; - RawAppend(scratch_buff, u"\n"); - RawAppend(scratch_buff, s); - } - - Caret caret = active.view->carets[0]; - SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets); - SelectEntireBuffer(active.view); - Replace(active.view, GetString(scratch_buff)); - active.view->carets[0] = caret; - } + Caret caret = active.view->carets[0]; + SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets); + SelectEntireBuffer(active.view); + Replace(active.view, GetString(scratch_buff)); + active.view->carets[0] = caret; } } -void CMD_SearchProject(HookParam param) { - BSet main = GetBSet(PrimaryWindowID); - String16 string = {}; - if (main.view->carets.len == 1 && GetSize(main.view->carets[0]) > 0) { - string = GetString(main.buffer, main.view->carets[0].range); - } - - NextActiveWindowID = main.window->id; - Buffer *search_project_buffer = GetBuffer(SearchProjectBufferID); - View *view = WindowOpenBufferView(main.window, search_project_buffer->name); - view->special = true; - view->kind = ViewKind_ActiveSearch; - AddCommand(&view->hooks, "Open", "ctrl-q | enter | f12", CMD_CommandWindowOpen); - SelectRange(view, GetLineRangeWithoutNL(search_project_buffer, 0)); - if (string.len) { - Replace(view, string); - SelectEntireBuffer(view); - } -} RegisterCommand(CMD_SearchProject, "ctrl-shift-f", "Interactive search over the entire project in a new buffer view"); - void SetFuzzy(View *view) { view->kind = ViewKind_FuzzySearch; - AddCommand(&view->hooks, "Open", "ctrl-q | enter | f12", CMD_CommandWindowOpen); + AddCommand(&view->hooks, "Open", "ctrl-q | enter | f12", [](HookParam){ + BSet active = GetBSet(ActiveWindowID); + BSet main = GetBSet(PrimaryWindowID); + NextActiveWindowID = main.window->id; + String16 string = FetchFuzzyViewLoadLine(active.view); + Open(string); + }); + AddHook(&view->hooks, HookKind_AppUpdate, "UpdateFuzzySearchView", "", UpdateFuzzySearchView); } -void CommandWindowInit() { +void LayoutCommandWindow(HookParam param) { + auto p = param.layout; + Rect2I copy_rect = *p.rect; + if (!p.window->visible) { + p.rect = ©_rect; + } + Int barsize = Clamp((Int)p.window->font->line_spacing*10, (Int)0, (Int)p.wx - 100); + p.window->document_rect = p.window->total_rect = CutBottom(p.rect, barsize); +} + +void InitCommandWindow(HookParam param) { Window *window = CreateWind(); CommandWindowID = window->id; Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "command_bar")); @@ -393,4 +249,5 @@ void CommandWindowInit() { window->sync_visibility_with_focus = true; window->lose_focus_on_escape = true; window->jump_history = false; -} + AddHook(&window->hooks, HookKind_LayoutWindow, "LayoutCommandWindow", "", LayoutCommandWindow); +} RegisterHook(InitCommandWindow, HookKind_AppInit, "", "Init command window");