diff --git a/build_file.cpp b/build_file.cpp index 1d188b1..ad3f78a 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -279,6 +279,8 @@ function SkipPath(s) if not slash_eaten then break end end + if #cells == 0 then return s end + local skip_size = input_s:len() - s:len() local path = input_s:sub(1, skip_size) return s, path, drive, cells @@ -297,6 +299,8 @@ end function MatchWindowsPath(_s) local s, file_path, drive = SkipPath(_s) + if not file_path then return nil end + if not drive then local d = GetActiveMainWindowBufferDir() file_path = d..'/'..file_path diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index c3e80b8..53417cf 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -17,20 +17,31 @@ void ToggleFullscreen() { void CheckpointBeforeGoto(Window *window, View *view) { Buffer *buffer = GetBuffer(view->active_buffer); - Add(&window->goto_history, {buffer->id, view->carets[0]}); - window->goto_redo.len = 0; + if (buffer->gc == false) { + Add(&window->goto_history, {buffer->id, view->carets[0]}); + window->goto_redo.len = 0; + } } void CheckpointBeforeGoto(Window *window) { CheckpointBeforeGoto(window, GetView(window->active_view)); } +GotoCrumb GetCrumb(Array *cr) { + for (; cr->len;) { + GotoCrumb c = Pop(cr); + Buffer *buffer = GetBufferStrict(c.buffer_id); + if (buffer) return c; + } + return {}; +} + void GotoBackward(Window *window) { BSet set = GetBSet(window); if (window->goto_history.len <= 0) return; Add(&window->goto_redo, {set.buffer->id, set.view->carets[0]}); - GotoCrumb c = Pop(&window->goto_history); + GotoCrumb c = GetCrumb(&window->goto_history); Buffer *buffer = GetBuffer(c.buffer_id); View *view = WindowOpenBufferView(window, buffer->name); view->carets[0] = c.caret; @@ -42,7 +53,7 @@ void GotoForward(Window *window) { if (window->goto_redo.len <= 0) return; Add(&window->goto_history, {set.buffer->id, set.view->carets[0]}); - GotoCrumb c = Pop(&window->goto_redo); + GotoCrumb c = GetCrumb(&window->goto_redo); Buffer *buffer = GetBuffer(c.buffer_id); View *view = WindowOpenBufferView(window, buffer->name); view->carets[0] = c.caret; @@ -604,6 +615,7 @@ void SaveBuffer(View *view) { if (success) { buffer->file_mod_time = GetFileModTime(buffer->name); buffer->dirty = false; + buffer->gc = false; } else { ReportWarningf("Failed to save file with name: %.*s", FmtString(buffer->name)); } diff --git a/src/text_editor/commands_bindings.cpp b/src/text_editor/commands_bindings.cpp index 42b1659..b376f77 100644 --- a/src/text_editor/commands_bindings.cpp +++ b/src/text_editor/commands_bindings.cpp @@ -469,7 +469,6 @@ void GlobalCommand(Event event) { if (GetSize(caret.range) == 0) range = EncloseLoadWord(active.buffer, GetFront(caret)); String16 string = GetString(active.buffer, range); - active.window->active_goto_list = active.view->id; Open(string); } diff --git a/src/text_editor/generated.cpp b/src/text_editor/generated.cpp index 88d7898..e2d84df 100644 --- a/src/text_editor/generated.cpp +++ b/src/text_editor/generated.cpp @@ -169,6 +169,8 @@ function SkipPath(s) if not slash_eaten then break end end + if #cells == 0 then return s end + local skip_size = input_s:len() - s:len() local path = input_s:sub(1, skip_size) return s, path, drive, cells @@ -187,6 +189,8 @@ end function MatchWindowsPath(_s) local s, file_path, drive = SkipPath(_s) + if not file_path then return nil end + if not drive then local d = GetActiveMainWindowBufferDir() file_path = d..'/'..file_path diff --git a/src/text_editor/lua_api.cpp b/src/text_editor/lua_api.cpp index 053ba4e..74d9347 100644 --- a/src/text_editor/lua_api.cpp +++ b/src/text_editor/lua_api.cpp @@ -42,6 +42,8 @@ void Open(String path) { return; } + BSet main = GetActiveMainSet(); + main.window->active_goto_list = main.view->id; if (FieldString(LuaState, "kind") == "text") { String file_path = FieldString(LuaState, "file_path"); String line_string = FieldString(LuaState, "line"); @@ -49,7 +51,6 @@ void Open(String path) { String col_string = FieldString(LuaState, "col"); Int col = strtoll(col_string.data, NULL, 10); - BSet main = GetActiveMainSet(); CheckpointBeforeGoto(main.window); View *view = WindowOpenBufferView(main.window, file_path); Buffer *buffer = GetBuffer(view->active_buffer); diff --git a/src/text_editor/management.cpp b/src/text_editor/management.cpp index 5f3385c..a3ca4bf 100644 --- a/src/text_editor/management.cpp +++ b/src/text_editor/management.cpp @@ -1,10 +1,10 @@ -WindowID WindowIDs = {0}; -BufferID BufferIDs = {0}; -ViewID ViewIDs = {0}; +WindowID WindowIDs; +BufferID BufferIDs; +ViewID ViewIDs; -Array Buffers = {}; -Array Views = {}; -Array Windows = {}; +Array Buffers; +Array Views; +Array Windows; BufferID NullBufferID; // +buffer ViewID NullViewID; @@ -58,6 +58,11 @@ inline Buffer *GetBuffer(BufferID id) { return Buffers[0].o; } +inline Buffer *GetBufferStrict(BufferID id) { + For(Buffers) if (it == id) return it.o; + return NULL; +} + inline Buffer *GetBuffer(String name) { For(Buffers) if (it.o->name == name) return it.o; return Buffers[0].o; @@ -124,9 +129,11 @@ Window *CreateWindow(bool insert_into_windows = true) { } View *CreateView(BufferID active_buffer) { - View *view = AllocType(Perm, View); - view->id = AllocViewID(view); - view->active_buffer = active_buffer; + Allocator al = GetSystemAllocator(); + View *view = AllocType(al, View); + view->id = AllocViewID(view); + view->active_buffer = active_buffer; + view->carets.allocator = al; Add(&view->carets, {0, 0}); Add(&Views, view->id); return view; @@ -410,6 +417,7 @@ Window *BufferIsCrumb(BufferID buffer_id) { } void GarbageCollect() { + Allocator sys_allocator = GetSystemAllocator(); IterRemove(Views) { IterRemovePrepare(Views); View *view = it.o; @@ -424,9 +432,9 @@ void GarbageCollect() { if (gc && !ref) { Dealloc(&view->carets); remove_item = true; - // @todo: add view to free list IKnowWhatImDoing_Appendf(GCInfoBuffer, "view %.*s\n", FmtString(buffer->name)); + Dealloc(sys_allocator, &view); } } @@ -442,9 +450,9 @@ void GarbageCollect() { DeallocHistoryArray(&buffer->redo_stack); Dealloc(buffer->line_starts.allocator, &buffer->data); remove_item = true; - // @todo: add buffer to free list IKnowWhatImDoing_Appendf(GCInfoBuffer, "buffer %.*s\n", FmtString(buffer->name)); + Dealloc(sys_allocator, &buffer); } else if (buffer->file_mod_time) { int64_t new_file_mod_time = GetFileModTime(buffer->name); if (buffer->file_mod_time != new_file_mod_time) { diff --git a/src/text_editor/todo.txt b/src/text_editor/todo.txt index 3a3cf4b..0fefec6 100644 --- a/src/text_editor/todo.txt +++ b/src/text_editor/todo.txt @@ -1,14 +1,11 @@ -- garbage collect the buffers, views - store them in free list on destroy - adding items to directory should create files on save - it should ask the user (syntax: dir/ | file) - ask user if he really wants to quit even though he has an unsaved buffer - popup window -- add plumb rules for some web stuff - test the code editor: try writing in it, try browsing in it, create test tooling - Execute enclosure which is going to execute on every keypress, modification - Find matches using grep, change things in that buffer then apply those changes to all items - group history entries so the you can rollback through multiple ones at once and not waste time on skipping whitespace trimming or deleting every character - Fuzzy search buffer which uses titlebar as query! -- Check if file exists in ApplyRules otherwise return null - Gotos, jumping between views should preserve cursors, maybe just scroll - ReportWarning should be signaled visibly but you should be able to do things! no focus switching