From 698212142902b582ec41c439e034ebf22c77b6b8 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 27 Jun 2026 17:14:02 +1000 Subject: [PATCH] fixes around saving, work towards updating current project on file change, more changes --- src/dlib | 2 +- src/editor/buffer.d | 14 +-- src/editor/editor.d | 242 +++++++++++++++++++++++--------------------- src/editor/main.d | 2 +- src/editor/ui.d | 12 ++- 5 files changed, 138 insertions(+), 134 deletions(-) diff --git a/src/dlib b/src/dlib index a12e8c2..253be45 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit a12e8c21e21b65e16af06675b6c2d1696e23bfa7 +Subproject commit 253be45581567c9108f9d2d686850c8862ab6168 diff --git a/src/editor/buffer.d b/src/editor/buffer.d index 1c48caf..4bfe8f8 100644 --- a/src/editor/buffer.d +++ b/src/editor/buffer.d @@ -1,7 +1,7 @@ import dlib; import dlib.alloc : Reset; import core.stdc.stdio : EOF; -import core.stdc.string : memcpy; +import core.stdc.string : memcpy, strlen; import parsing; import std.format : sformat; import std.math.algebraic : abs; @@ -68,9 +68,9 @@ struct FlatBuffer this.arena = CreateArena(MB(1)); this.line_start_arena = CreateArena(KB(512)); - this.file_name = file_name; + this.file_name = AllocTerminated(file_name); this.line_count = CountLF(data); - this.length = data.length; + this.length = data.ptr ? strlen(cast(char*)data.ptr) : 0; this.linebufs = CreateLineBuffers(MB(1)); this.data = buffer; this.tokenizer = CreateTokenizer(&this); @@ -218,11 +218,7 @@ OpenFile(Editor* editor, string file_name) } else { - char[] file_name_buffer = Alloc!(char)(file_path.length+1); - file_name_buffer[0 .. file_path.length] = file_path[0 .. $]; - file_name_buffer[file_name_buffer.length-1] = '\0'; - - file_path = Str(file_name_buffer); + file_path = AllocTerminated(file_path); u8[] file_data; auto file = fopen(file_path.ptr, "rb"); @@ -238,7 +234,7 @@ OpenFile(Editor* editor, string file_name) fread(file_data.ptr, u8.sizeof, length, file); } - editor.buffer = CreateFlatBuffer(ctx, file_data, Str(file_name_buffer)); + editor.buffer = CreateFlatBuffer(ctx, file_data, file_path); } else { diff --git a/src/editor/editor.d b/src/editor/editor.d index 8fe632c..66206d5 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -11,6 +11,7 @@ import parsing; import std.algorithm.comparison : clamp; import std.format; +import std.array; import std.stdio; import std.exception; import std.file; @@ -95,6 +96,7 @@ struct Ctx u64 editor_id_incr; Timer timer; CmdPalette cmd; + Arena file_name_arena; string[] file_names; u64 panel_id; Editor[] editors; @@ -105,6 +107,8 @@ struct Ctx FlatBuffer* free_text_buffers; u64 new_buffer_count; // files that are not yet files (you know) + Watcher directory_watcher; + @property ref DescSet desc_set() => this.rd_ctx.desc_sets[this.frame_index]; debug bool dbg; @@ -255,12 +259,9 @@ __gshared UIInput* g_UI_NIL_INPUT = &g_ui_nil_input; __gshared UIPanel* g_NIL_PANEL = &g_nil_panel; __gshared Notification* g_NIL_NOTIF = &g_nil_notif; -const Command NO_CMD = { - name: [], - type: CT.None, -}; +immutable Command NO_CMD; -Command[22] CMD_LIST = [ +Command[8] CMD_LIST = [ { name: "Open", cmd: "open", @@ -277,7 +278,7 @@ Command[22] CMD_LIST = [ }, { name: "Save As", - cmd: "save as", + cmd: "saveas", desc: "Save the current file as a specified name.", type: CT.Callback, fn: &CmdSaveFileWindow, @@ -311,109 +312,11 @@ Command[22] CMD_LIST = [ fn: &ClosePanelCmd, }, { - name: "Test Option 1", - cmd: "testopt1", - desc: "This is a test option", + name: "Quit", + cmd: "quit", + desc: "Close the program.", type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 2", - cmd: "testopt2", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 3", - cmd: "testopt3", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 4", - cmd: "testopt4", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 5", - cmd: "testopt5", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 6", - cmd: "testopt6", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 7", - cmd: "testopt7", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 8", - cmd: "testopt8", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 9", - cmd: "testopt9", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 10", - cmd: "testopt10", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 11", - cmd: "testopt11", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 12", - cmd: "testopt12", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 13", - cmd: "testopt13", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 14", - cmd: "testopt14", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, - }, - { - name: "Test Option 15", - cmd: "testopt15", - desc: "This is a test option", - type: CT.Callback, - fn: &NotImplementedCallback, + fn: &CmdClose, }, ]; @@ -525,11 +428,24 @@ Cycle(Inputs* inputs) { ResetScratch(MB(4)); - g_delta = DeltaTime(&g_ctx.timer); + ref Ctx ctx = GetCtx(); + + WatchEvent[] watch_events = ViewChanges(&ctx.directory_watcher); + foreach(ref event; watch_events) + { + Logf("type %s", event.type); + if(event.type & WET.File && event.type & (WET.Created | WET.Moved | WET.Deleted)) + { + Logf("scanning..."); + ScanCurrentDirectory(ctx); + break; + } + } + + g_delta = DeltaTime(&g_ctx.timer); BeginUI(inputs); - ref Ctx ctx = GetCtx(); Panel(ctx, ctx.base_panel); @@ -559,7 +475,8 @@ InitCtx(PlatformWindow* window) ref Ctx ctx = GetCtx(); ctx.window = window; - ctx.arena = CreateArena(MB(2)); + ctx.arena = CreateArena(MB(1)); + ctx.file_name_arena = CreateArena(MB(1)); ctx.cmd.text_input.data = Alloc!(u8)(1024); ctx.cmd.exec_cmd_input.data = Alloc!(u8)(1024); ctx.cmd.exec_cmd_arena = CreateArena(MB(1)); @@ -573,29 +490,118 @@ InitCtx(PlatformWindow* window) ctx.base_panel = CreatePanel(); Focus(ctx.base_panel); + ScanCurrentDirectory(ctx); + + ctx.directory_watcher = WatchDirectory(".", WT.Create|WT.Delete|WT.Moved); +} + +u8[] +OpenFile(string file_name) nothrow @nogc +{ + File* file; + u8[] data; + + file = FOpen(file_name.ptr, "rb"); + if(file) + { + FSeek(file, 0, SeekEnd); + u64 size = FTell(file); + FSeek(file, 0, SeekSet); + + data = Alloc!(u8)(size); + + FRead(data.ptr, 1, size, file); + + FClose(file); + } + + return data; +} + +void +ScanCurrentDirectory(ref Ctx ctx) +{ + Reset(&ctx.file_name_arena); + ctx.file_names = []; + if(getcwd() != "/") { + string[] ignore_lines; + u8[] ignore_file = OpenFile(".ignore"); + if(ignore_file.length) + { + u64 ignore_line_count = 1; + for(u64 i = 0; i < ignore_file.length; i += 1) + { + if(ignore_file[i] == '\n') + { + ignore_line_count += 1; + } + } + + ignore_lines = Alloc!(string)(&ctx.file_name_arena, ignore_line_count); + + u64 current_count; + u64 start; + for(u64 i = 0; i < ignore_file.length; i += 1) + { + if(ignore_file[i] == '\n') + { + ignore_lines[current_count++] = Str(ignore_file[start .. i]); + start = ++i; + } + } + } + // TODO: replace this with something nogc/nothrow try { u64 count = 0; - foreach(DirEntry e; dirEntries(".", SpanMode.breadth)) + foreach(ref DirEntry e; dirEntries(".", SpanMode.breadth)) { - if(indexOf(e.name, ".git") != -1 || e.isDir) continue; + if(e.isDir) continue; u64 start = indexOf(e.name, "./") == 0 ? 2 : 0; - count += 1; + + bool ignored; + foreach(ref ignore_line; ignore_lines) + { + if(ignore_line.length && StrContains!(true)(e.name[start .. $], ignore_line)) + { + ignored = true; + break; + } + } + + if(!ignored) + { + count += 1; + } } ctx.file_names = Alloc!(string)(&ctx.arena, count); count = 0; - foreach(DirEntry e; dirEntries(".", SpanMode.breadth)) + foreach(ref DirEntry e; dirEntries(".", SpanMode.breadth)) { - if(indexOf(e.name, ".git") != -1 || e.isDir) continue; + if(e.isDir) continue; - u64 start = indexOf(e.name, "./") == 0 ? 2 : 0; - ctx.file_names[count++] = Alloc(&ctx.arena, e.name); + u64 start = indexOf(e.name, "./") == 0 ? 2 : 0; + + bool ignored; + foreach(ref ignore_line; ignore_lines) + { + if(ignore_line.length && StrContains!(true)(e.name[start .. $], ignore_line)) + { + ignored = true; + break; + } + } + + if(!ignored) + { + ctx.file_names[count++] = Alloc(&ctx.arena, e.name[start .. $]); + } } } catch(Exception e) diff --git a/src/editor/main.d b/src/editor/main.d index 824a928..3eb31d2 100644 --- a/src/editor/main.d +++ b/src/editor/main.d @@ -34,7 +34,7 @@ void main(string[] argv) import vulkan; u64 no_ev_count; - while (true) + while(true) { Inputs* inputs = GetEvents(&window); if(window.close) diff --git a/src/editor/ui.d b/src/editor/ui.d index ed50077..e4f21bf 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -409,13 +409,9 @@ InitUI(ref Ctx ctx) } } - Arena arena = CreateArena(MB(4)); - UIBuffer[FRAME_OVERLAP] buffers; ctx.items = CreateHashTable!(UIHash, UIItem*)(12); - ctx.arena = arena; - ctx.temp_arena = CreateArena(MB(1)); ctx.font = OpenFont(cast(u8[])FONT_BYTES); ctx.tab_width = 2; ctx.syntax_colors = [DEFAULT_COLORS, SYNTAX_COLORS]; @@ -1056,6 +1052,12 @@ SearchInputWindow(T)(string hash_text, SearchWindowCtx!(T)* window_ctx, bool rea } } +bool +CmdClose(ref Ctx ctx) +{ + return true; +} + bool CmdSaveFile(ref Ctx ctx) { @@ -1103,7 +1105,7 @@ CmdSaveFileWindow(ref Ctx ctx) f32 inner_x = x + PAD; f32 inner_y = y + PAD; - Rect window_rect = Rect(p0: Vec2(x, y), p1: Vec2(x+w, y+h)); + Rect window_rect = Rect(p0: Vec2(x, y), p1: Vec2(x+w, y+h)); Rect inner_rect = Rect(p0: Vec2(inner_x, inner_y), p1: Vec2(inner_x+inner_w, inner_y+inner_h)); DrawRect(ctx, window_rect, &CMD_STYLE);