BIG OPTIMIZATIONS: WTF IT WORKS SO FAST NOW, 9000 files open easy WHAAAT
This commit is contained in:
@@ -226,11 +226,9 @@ API String16 GetLineStringWithoutNL(Buffer *buffer, Int line) {
|
||||
API Int PosToLine(Buffer *buffer, Int pos) {
|
||||
Add(&buffer->line_starts, buffer->len + 1);
|
||||
|
||||
// binary search
|
||||
Int low = 0;
|
||||
|
||||
// -2 here because we use 2 indices and combine them into one line range so we
|
||||
// don't want to access last item since that would index past array.
|
||||
Int low = 0;
|
||||
Int high = buffer->line_starts.len - 2;
|
||||
Int result = 0;
|
||||
|
||||
@@ -745,7 +743,6 @@ inline bool MergeSortCompare(Edit *EntryA, Edit *EntryB) {
|
||||
|
||||
template<class T>
|
||||
void MergeSort(int64_t Count, T *First, T *Temp) {
|
||||
ProfileFunction();
|
||||
// SortKey = range.min
|
||||
if (Count == 1) {
|
||||
// NOTE(casey): No work to do.
|
||||
@@ -823,7 +820,9 @@ API void ApplyEditsMultiCursor(Buffer *buffer, Array<Edit> edits) {
|
||||
// We need to sort from lowest to highest based on range.min
|
||||
Scratch scratch(buffer->line_starts.allocator);
|
||||
Array<Edit> edits_copy = TightCopy(scratch, edits);
|
||||
if (edits.len > 1) MergeSort(edits.len, edits_copy.data, edits.data);
|
||||
if (edits.len > 1) {
|
||||
MergeSort(edits.len, edits_copy.data, edits.data);
|
||||
}
|
||||
edits = edits_copy;
|
||||
|
||||
#if BUFFER_DEBUG
|
||||
@@ -1368,14 +1367,28 @@ BufferID AllocBufferID(Buffer *buffer) {
|
||||
}
|
||||
|
||||
Buffer *GetBuffer(BufferID id, Buffer *default_buffer = Buffers[0]) {
|
||||
For(Buffers) {
|
||||
if (it->id == id) return it;
|
||||
Int left = 0;
|
||||
Int right = Buffers.len - 1;
|
||||
Buffer *result = default_buffer;
|
||||
|
||||
while (left <= right) {
|
||||
Int mid = left + (right - left) / 2;
|
||||
Buffer *it = Buffers[mid];
|
||||
if (it->id == id) {
|
||||
result = it;
|
||||
break;
|
||||
} else if (it->id.id < id.id) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
return default_buffer;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Buffer *GetBuffer(String name, Buffer *default_buffer = Buffers[0]) {
|
||||
For(Buffers) {
|
||||
For (Buffers) {
|
||||
if (it->name == name) return it;
|
||||
}
|
||||
return default_buffer;
|
||||
@@ -1506,18 +1519,6 @@ Buffer *BufferOpenFile(String path) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool BufferIsReferenced(Buffer *buffer) {
|
||||
if (buffer->special) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FindView(buffer->id, NULL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReopenBuffer(Buffer *buffer) {
|
||||
Scratch scratch;
|
||||
|
||||
@@ -1566,3 +1567,15 @@ String GetDirectory(Buffer *buffer) {
|
||||
String result = ChopLastSlash(buffer->name);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TryReopeningWhenModified(Buffer *it) {
|
||||
if (it->file_mod_time) {
|
||||
int64_t new_file_mod_time = GetFileModTime(it->name);
|
||||
if (it->file_mod_time != new_file_mod_time) {
|
||||
it->changed_on_disk = true;
|
||||
if (it->dirty == false) {
|
||||
ReopenBuffer(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,18 +103,14 @@ void ReportErrorf(const char *fmt, ...) {
|
||||
BREAK();
|
||||
}
|
||||
|
||||
View *view = GetView(LogViewID);
|
||||
if (view) {
|
||||
Appendf(view, "%S\n", string);
|
||||
}
|
||||
Appendf(LogView, "%S\n", string);
|
||||
ShowUIMessagef("%S", string);
|
||||
}
|
||||
|
||||
void ReportConsolef(const char *fmt, ...) {
|
||||
Scratch scratch;
|
||||
STRING_FORMAT(scratch, fmt, string);
|
||||
View *view = GetView(LogViewID);
|
||||
Appendf(view, "%S\n", string);
|
||||
Appendf(LogView, "%S\n", string);
|
||||
}
|
||||
|
||||
void ReportWarningf(const char *fmt, ...) {
|
||||
@@ -124,8 +120,7 @@ void ReportWarningf(const char *fmt, ...) {
|
||||
if (BreakOnError) {
|
||||
BREAK();
|
||||
}
|
||||
View *null_view = GetView(LogViewID);
|
||||
Appendf(null_view, "%S\n", string);
|
||||
Appendf(LogView, "%S\n", string);
|
||||
}
|
||||
|
||||
void CMD_CenterView() {
|
||||
@@ -177,8 +172,7 @@ void ApplyFormattingTool(Buffer *buffer, String tool) {
|
||||
if (exec_result.exit_code == 0) {
|
||||
ReplaceWithoutMovingCarets(buffer, GetRange(buffer), string16);
|
||||
} else {
|
||||
View *view = GetView(LogViewID);
|
||||
Append(view, string16, true);
|
||||
Append(LogView, string16, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,8 +244,7 @@ void CMD_ToggleFullscreen() {
|
||||
|
||||
void CMD_OpenLogs() {
|
||||
ErrorCount = 0;
|
||||
Buffer *buffer = GetBuffer(LogBufferID);
|
||||
Open(buffer->name);
|
||||
Open(LogBuffer->name);
|
||||
} RegisterCommand(CMD_OpenLogs, "", "Opens the text editor logs and clear error counter");
|
||||
|
||||
void CMD_Errors() {
|
||||
|
||||
@@ -29,8 +29,8 @@ Array<Window *> Windows;
|
||||
Array<View *> Views;
|
||||
Array<Buffer *> Buffers;
|
||||
|
||||
BufferID LogBufferID;
|
||||
ViewID LogViewID;
|
||||
View *LogView;
|
||||
Buffer *LogBuffer;
|
||||
|
||||
BufferID NullBufferID;
|
||||
ViewID NullViewID;
|
||||
|
||||
@@ -2111,7 +2111,7 @@ bool RDBG_InitConnection(mco_coro *co, bool create_session = true) {
|
||||
String session_name = Format(CoCurr->arena, "te%llu", GetTimeNanos());
|
||||
String remedy_string = Format(CoCurr->arena, "%S --servername %S", RemedyBGPath, session_name);
|
||||
ReportConsolef("Remedybg: %S", remedy_string);
|
||||
Exec(LogViewID, true, remedy_string, GetPrimaryDirectory());
|
||||
Exec(LogView->id, true, remedy_string, GetPrimaryDirectory());
|
||||
MemoryZero(&RDBG_Ctx, sizeof(RDBG_Ctx));
|
||||
RDBG_Ctx.cmd.data = command_buf;
|
||||
RDBG_Ctx.cmd.capacity = sizeof(command_buf);
|
||||
|
||||
@@ -89,15 +89,17 @@ void LayoutSearchWindow(Rect2I *rect, int16_t wx, int16_t wy) {
|
||||
window->line_numbers_rect = CutLeft(&window->document_rect, window->font->char_spacing * 6);
|
||||
}
|
||||
|
||||
Int SearchBufferChangeID;
|
||||
void UpdateSearchWindow() {
|
||||
if (ActiveWindowID == SearchWindowID) {
|
||||
BSet active = GetBSet(ActiveWindowID);
|
||||
if (active.buffer->begin_frame_change_id != active.buffer->change_id) {
|
||||
if (SearchBufferChangeID != active.buffer->change_id) {
|
||||
BSet main = GetBSet(PrimaryWindowID);
|
||||
main.view->carets[0] = main.window->search_bar_anchor;
|
||||
String16 seek = GetString(active.buffer, GetRange(active.buffer));
|
||||
Find(main.view, seek, true);
|
||||
CenterView(main.window->id);
|
||||
SearchBufferChangeID = active.buffer->change_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ void UpdateProcesses() {
|
||||
IterRemove(ActiveProcesses) {
|
||||
IterRemovePrepare(ActiveProcesses);
|
||||
Scratch scratch;
|
||||
View *view = GetView({it.view_id});
|
||||
View *view = GetView(ViewID{it.view_id});
|
||||
|
||||
String poll = PollStdout(scratch, &it, false);
|
||||
if (poll.len) {
|
||||
|
||||
@@ -572,7 +572,7 @@ void GarbageCollect() {
|
||||
Dealloc(sys_allocator, it);
|
||||
remove_item = true;
|
||||
} else {
|
||||
View *view = FindView(it->active_view, NULL);
|
||||
View *view = GetView(it->active_view, NULL);
|
||||
if (!view) {
|
||||
JumpToLastValidView(it);
|
||||
}
|
||||
@@ -685,14 +685,6 @@ void Update(Event event) {
|
||||
UpdateScroll(it, !AreEqual(view->main_caret_on_begin_frame, view->carets[0]) && view->update_scroll);
|
||||
}
|
||||
|
||||
// We update it here despite the name to make it sure that all the possible changes are
|
||||
// included albeit with delayed response. If we did this at the beginning of the frame
|
||||
// and the DebugWindowUpdated we wouldnt get to know that in the OnCommand.
|
||||
// @todo: this is slow, we don't want to loop through every buffer on every frame :(
|
||||
For (Buffers) {
|
||||
it->begin_frame_change_id = it->change_id;
|
||||
}
|
||||
|
||||
{
|
||||
ProfileScope(UpdateWindows);
|
||||
For (Windows) {
|
||||
@@ -775,20 +767,10 @@ void Update(Event event) {
|
||||
}
|
||||
}
|
||||
|
||||
// Reopen modified buffers
|
||||
// @todo: This is O(n) so could see slow downs with number of buffers, likely need OS help to make it more
|
||||
// efficient
|
||||
// @todo: maybe instead go through windows and only reopen active buffers
|
||||
For(Buffers) {
|
||||
if (it->file_mod_time) {
|
||||
int64_t new_file_mod_time = GetFileModTime(it->name);
|
||||
if (it->file_mod_time != new_file_mod_time) {
|
||||
it->changed_on_disk = true;
|
||||
if (it->dirty == false) {
|
||||
ReopenBuffer(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
// IS THIS ENOUGH? Previously reopened everything
|
||||
For (Windows) {
|
||||
BSet set = GetBSet(it);
|
||||
TryReopeningWhenModified(set.buffer);
|
||||
}
|
||||
|
||||
GarbageCollect();
|
||||
@@ -984,10 +966,10 @@ int main(int argc, char **argv)
|
||||
|
||||
Buffer *logs_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(ProjectDirectory, "logs", ""));
|
||||
logs_buffer->special = true;
|
||||
LogBufferID = logs_buffer->id;
|
||||
View *logs_view = CreateView(logs_buffer->id);
|
||||
logs_view->special = true;
|
||||
LogViewID = logs_view->id;
|
||||
LogBuffer = logs_buffer;
|
||||
LogView = logs_view;
|
||||
|
||||
#if PLUGIN_RECORD_GC
|
||||
GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(ProjectDirectory, "gc"));
|
||||
|
||||
@@ -70,9 +70,7 @@ struct ResolvedOpen {
|
||||
struct Buffer {
|
||||
BufferID id;
|
||||
String name;
|
||||
Int begin_frame_change_id;
|
||||
Int change_id;
|
||||
Int user_change_id;
|
||||
Int file_mod_time;
|
||||
|
||||
union {
|
||||
@@ -338,7 +336,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 = "");
|
||||
View *FindView(BufferID buffer_id, View *default_view = NULL);
|
||||
|
||||
bool operator==(BufferID a, BufferID b) { return a.id == b.id; }
|
||||
bool operator==(ViewID a, ViewID b) { return a.id == b.id; }
|
||||
|
||||
@@ -365,7 +365,7 @@ BSet Open(Window *window, String path, ResolveOpenMeta meta, bool set_active = t
|
||||
Exec(set.view->id, false, o.path, GetPrimaryDirectory());
|
||||
} else if (o.kind == OpenKind_BackgroundExec) {
|
||||
// this shouldn't change the focus/window/view
|
||||
Exec(LogViewID, false, o.path, GetPrimaryDirectory());
|
||||
Exec(LogView->id, false, o.path, GetPrimaryDirectory());
|
||||
} else if (o.kind == OpenKind_Command) {
|
||||
EvalCommand(o.path);
|
||||
}
|
||||
|
||||
@@ -20,18 +20,29 @@ void Dealloc(View *view) {
|
||||
Dealloc(view->carets.allocator, view);
|
||||
}
|
||||
|
||||
// TODO: default_view should probably be Views[0] but could break stuff
|
||||
API View *FindView(ViewID view_id, View *default_view = NULL) {
|
||||
For(Views) {
|
||||
if (it->id == view_id) {
|
||||
return it;
|
||||
View *GetView(ViewID id, View *default_view = Views[0]) {
|
||||
Int left = 0;
|
||||
Int right = Views.len - 1;
|
||||
View *result = default_view;
|
||||
|
||||
while (left <= right) {
|
||||
Int mid = left + (right - left) / 2;
|
||||
View *it = Views[mid];
|
||||
if (it->id == id) {
|
||||
result = it;
|
||||
break;
|
||||
} else if (it->id.id < id.id) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
return default_view;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
API View *FindView(BufferID buffer_id, View *default_view) {
|
||||
For(Views) {
|
||||
API View *GetView(BufferID buffer_id, View *default_view = Views[0]) {
|
||||
For (Views) {
|
||||
if (it->active_buffer == buffer_id) {
|
||||
return it;
|
||||
}
|
||||
@@ -39,8 +50,8 @@ API View *FindView(BufferID buffer_id, View *default_view) {
|
||||
return default_view;
|
||||
}
|
||||
|
||||
API View *FindView(String name, View *default_view = NULL) {
|
||||
For(Views) {
|
||||
API View *GetView(String name, View *default_view = Views[0]) {
|
||||
For (Views) {
|
||||
Buffer *buffer = GetBuffer(it->active_buffer);
|
||||
if (buffer->name == name) {
|
||||
return it;
|
||||
@@ -49,10 +60,6 @@ API View *FindView(String name, View *default_view = NULL) {
|
||||
return default_view;
|
||||
}
|
||||
|
||||
API View *GetView(ViewID id) {
|
||||
return FindView(id, Views[0]);
|
||||
}
|
||||
|
||||
API View *OpenBufferView(String name) {
|
||||
Buffer *buffer = BufferOpenFile(name);
|
||||
View *view = CreateView(buffer->id);
|
||||
@@ -88,10 +95,22 @@ API bool ViewIsReferenced(View *view) {
|
||||
return ViewIsActive(view->id);
|
||||
}
|
||||
|
||||
bool BufferIsReferenced(Buffer *buffer) {
|
||||
if (buffer->special) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetView(buffer->id, NULL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Close(ViewID id) {
|
||||
View *view = GetView(id);
|
||||
View *view = GetView(id, NULL);
|
||||
if (view) {
|
||||
if (view->id.id == 0) {
|
||||
if (view->special) {
|
||||
return;
|
||||
}
|
||||
view->close = true;
|
||||
|
||||
@@ -45,19 +45,24 @@ Window *FindWindow(ViewID view_id, Window *default_window = NULL) {
|
||||
|
||||
Window *FindWindow(String buffer_name, Window *default_window = NULL) {
|
||||
For(Windows) {
|
||||
View *it_view = GetView(it->active_view);
|
||||
Buffer *it_buffer = GetBuffer(it_view->active_buffer);
|
||||
if (it_buffer->name == buffer_name) {
|
||||
return it;
|
||||
View *it_view = GetView(it->active_view, NULL);
|
||||
if (it_view) {
|
||||
Buffer *it_buffer = GetBuffer(it_view->active_buffer, NULL);
|
||||
Assert(it_buffer); // Probably we are missing something when GCing / closing
|
||||
if (it_buffer && it_buffer->name == buffer_name) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
}
|
||||
return default_window;
|
||||
}
|
||||
|
||||
Window *FindWindow(BufferID buffer_id) {
|
||||
For(Windows) {
|
||||
View *view = GetView(it->active_view);
|
||||
if (view->active_buffer == buffer_id) return it;
|
||||
For (Windows) {
|
||||
View *view = GetView(it->active_view, Views[0]);
|
||||
if (view->active_buffer == buffer_id) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -92,7 +97,7 @@ Int GetExpandingBarSize(Window *window) {
|
||||
}
|
||||
|
||||
View *WindowOpenBufferView(Window *new_parent_window, String name) {
|
||||
View *view = FindView(name);
|
||||
View *view = GetView(name, NULL);
|
||||
if (!view) {
|
||||
View *result = OpenBufferView(name);
|
||||
new_parent_window->active_view = result->id;
|
||||
@@ -192,7 +197,7 @@ Int ScreenSpaceToBufferPosErrorOutOfBounds(Window *window, View *view, Buffer *b
|
||||
GotoCrumb PopCrumb(Array<GotoCrumb> *cr) {
|
||||
for (; cr->len;) {
|
||||
GotoCrumb c = Pop(cr);
|
||||
View *view = FindView(c.view_id, NULL);
|
||||
View *view = GetView(c.view_id, NULL);
|
||||
if (view) {
|
||||
return c;
|
||||
}
|
||||
@@ -203,12 +208,12 @@ GotoCrumb PopCrumb(Array<GotoCrumb> *cr) {
|
||||
View *GetLastValidView(Window *window) {
|
||||
For (IterateInReverse(&window->goto_redo)) {
|
||||
if (it.view_id == window->active_view) continue;
|
||||
View *view = FindView(it.view_id, NULL);
|
||||
View *view = GetView(it.view_id, NULL);
|
||||
if (view) return view;
|
||||
}
|
||||
For (IterateInReverse(&window->goto_history)) {
|
||||
if (it.view_id == window->active_view) continue;
|
||||
View *view = FindView(it.view_id, NULL);
|
||||
View *view = GetView(it.view_id, NULL);
|
||||
if (view) return view;
|
||||
}
|
||||
return Views[0];
|
||||
|
||||
Reference in New Issue
Block a user