From 4871494c50c5cbdb5fc4f376673d2f6a7beb71d4 Mon Sep 17 00:00:00 2001 From: krzosa Date: Fri, 2 May 2025 12:53:13 +0200 Subject: [PATCH] Eval on click, fix reopen buffers, detecting change --- data/init.lua | 2 - src/basic/filesystem.h | 4 +- src/text_editor/buffer.cpp | 12 +++--- src/text_editor/commands.cpp | 14 ++---- src/text_editor/commands_bindings.cpp | 30 +++++++------ src/text_editor/generated.cpp | 2 - src/text_editor/lua_api.cpp | 35 +++++++-------- src/text_editor/management.cpp | 61 ++++++++++++++++----------- src/text_editor/text_editor.cpp | 2 +- src/text_editor/text_editor.h | 5 +-- src/text_editor/title_bar.cpp | 2 +- src/text_editor/todo.txt | 18 +------- src/text_editor/window.cpp | 4 +- 13 files changed, 90 insertions(+), 101 deletions(-) diff --git a/data/init.lua b/data/init.lua index 577a374..1ec6e3b 100644 --- a/data/init.lua +++ b/data/init.lua @@ -230,8 +230,6 @@ OnCommandCallbacks = {} table.insert(OnCommandCallbacks, function (e) if e.key == SDLK_F and e.ctrl == 1 and e.shift == 1 then C("git grep -n "..GetLoadWord().." :/") end - if e.key == SDLK_L and e.ctrl == 1 then - Eval(GetLoadWord()) end end) function OnUpdate(e) diff --git a/src/basic/filesystem.h b/src/basic/filesystem.h index 18bd612..4cd5687 100644 --- a/src/basic/filesystem.h +++ b/src/basic/filesystem.h @@ -47,4 +47,6 @@ bool IsValid(Process *process); void KillProcess(Process *process); String PollStdout(Allocator allocator, Process *process); void WriteStdin(Process *process, String string); -void CloseStdin(Process *process); \ No newline at end of file +void CloseStdin(Process *process); + +double get_time_in_micros(void); \ No newline at end of file diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index a1c14ca..8d30e55 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -114,13 +114,13 @@ Caret SetFront(Caret caret, Int front) { return result; } -Caret SetFrontWithAnchor(Caret caret, Range anchor, Int p) { - if (anchor.min > p) { - caret = MakeCaret(p, anchor.max); - } else if (anchor.max < p) { - caret = MakeCaret(p, anchor.min); +Caret SetFrontWithAnchor(Caret caret, Caret anchor, Int p) { + if (anchor.range.min > p) { + caret = MakeCaret(p, anchor.range.max); + } else if (anchor.range.max < p) { + caret = MakeCaret(p, anchor.range.min); } else { - caret = MakeCaret(anchor.max, anchor.min); + caret = anchor; } return caret; } diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index cb81805..f021e95 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -90,7 +90,7 @@ void Command_ListBuffers() { String result = Merge(scratch, strings, "\n"); String16 string16 = ToString16(scratch, result); - String buffer_name = GetUniqueBufferName(scratch, GetDir(main.buffer), "+list_buffers-"); + String buffer_name = GetUniqueBufferName(GetDir(main.buffer), "+list_buffers-"); View *new_view = WindowOpenBufferView(main.window, buffer_name); Buffer *new_buffer = GetBuffer(new_view->active_buffer); new_buffer->gc = true; @@ -100,7 +100,7 @@ void Command_ListBuffers() { Command_SelectRangeOneCursor(new_view, {}); } -void MouseLoadWord(Event event, bool cut_path) { +void MouseLoadWord(Event event, void (*cmd_function)(String16 string)) { Vec2I mouse = MouseVec2I(); BSet active = GetActiveSet(); @@ -111,18 +111,10 @@ void MouseLoadWord(Event event, bool cut_path) { Range enclose = EncloseLoadWord(active.buffer, p); if (InBounds(active.view->carets[0].range, p)) enclose = active.view->carets[0].range; String16 string = GetString(active.buffer, enclose); - Scratch scratch; - if (cut_path) { - string = NormalizePath(scratch, string); - String16 right_part = CutLastSlash(&string); - if (right_part.len > 1 && right_part.data[1] == u'+') { - CutLastSlash(&string); - } - } active.view->carets.len = 1; active.view->carets[0] = MakeCaret(p); - Command_Open(string); + cmd_function(string); } } } diff --git a/src/text_editor/commands_bindings.cpp b/src/text_editor/commands_bindings.cpp index 076a812..6920d92 100644 --- a/src/text_editor/commands_bindings.cpp +++ b/src/text_editor/commands_bindings.cpp @@ -34,11 +34,20 @@ void ListFilesRecursive(Buffer *buffer, String filename) { } } +String16 FetchLoadWord(void) { + BSet active = GetActiveSet(); + Caret caret = active.view->carets[0]; + Range range = caret.range; + if (GetSize(caret.range) == 0) range = EncloseLoadWord(active.buffer, GetFront(caret)); + String16 string = GetString(active.buffer, range); + return string; +} + void Command_GetCFiles(void) { BSet main = GetActiveMainSet(); Scratch scratch; - String buffer_name = GetUniqueBufferName(scratch, GetDir(main.buffer), "+ls-"); + String buffer_name = GetUniqueBufferName(GetDir(main.buffer), "+ls-"); Buffer *buffer = CreateBuffer(GetSystemAllocator(), buffer_name, 4096 * 4); ListFilesRecursive(buffer, Command_GetDir()); @@ -149,7 +158,7 @@ void OnCommand(Event event) { Int p = ScreenSpaceToBufferPos(selected.window, selected.view, selected.buffer, mouse); Caret &caret = selected.view->carets[0]; - caret = SetFrontWithAnchor(caret, DocumentRangeAnchor, p); + caret = SetFrontWithAnchor(caret, DocumentAnchor, p); } // Set active window on click @@ -209,9 +218,9 @@ void OnCommand(Event event) { } if (Shift() && Ctrl() && Mouse(LEFT)) { - MouseLoadWord(event, true); + MouseLoadWord(event, Command_Eval); } else if (Ctrl() && Mouse(LEFT)) { - MouseLoadWord(event, false); + MouseLoadWord(event, Command_Open); } else if (Mouse(LEFT)) { // Uses Alt and shift Vec2I mouse = MouseVec2I(); { @@ -219,7 +228,6 @@ void OnCommand(Event event) { Assert(DocumentSelected.id == -1); BSet active = GetActiveSet(); - bool mouse_in_document = CheckCollisionPointRec(mouse, active.window->document_rect); bool mouse_in_line_numbers = CheckCollisionPointRec(mouse, active.window->line_numbers_rect); if (mouse_in_document || mouse_in_line_numbers) { @@ -249,7 +257,7 @@ void OnCommand(Event event) { caret = MakeCaret(p); } MergeCarets(active.buffer, &active.view->carets); - DocumentRangeAnchor = caret.range; + DocumentAnchor = caret; } } @@ -525,13 +533,11 @@ void OnCommand(Event event) { } - if (CtrlPress(SDLK_Q)) { - Caret caret = active.view->carets[0]; - Range range = caret.range; - if (GetSize(caret.range) == 0) range = EncloseLoadWord(active.buffer, GetFront(caret)); - String16 string = GetString(active.buffer, range); - Command_Open(string); + if (CtrlShiftPress(SDLK_Q)) { + Command_Eval(FetchLoadWord()); + } else if (CtrlPress(SDLK_Q)) { + Command_Open(FetchLoadWord()); } if (Press(SDLK_ESCAPE)) { diff --git a/src/text_editor/generated.cpp b/src/text_editor/generated.cpp index 0c6fd2c..1eea2bc 100644 --- a/src/text_editor/generated.cpp +++ b/src/text_editor/generated.cpp @@ -299,8 +299,6 @@ OnCommandCallbacks = {} table.insert(OnCommandCallbacks, function (e) if e.key == SDLK_F and e.ctrl == 1 and e.shift == 1 then C("git grep -n "..GetLoadWord().." :/") end - if e.key == SDLK_L and e.ctrl == 1 then - Eval(GetLoadWord()) end end) function OnUpdate(e) diff --git a/src/text_editor/lua_api.cpp b/src/text_editor/lua_api.cpp index 2d58d36..34cb34a 100644 --- a/src/text_editor/lua_api.cpp +++ b/src/text_editor/lua_api.cpp @@ -18,7 +18,7 @@ void Command_ExecInNewBuffer(BSet set, String cmd, String working_dir) { CheckpointBeforeGoto(set.window); Scratch scratch; - String buffer_name = GetUniqueBufferName(scratch, working_dir, "+cmd-"); + String buffer_name = GetUniqueBufferName(working_dir, "+cmd-"); View *view = WindowOpenBufferView(set.window, buffer_name); Buffer *buffer = GetBuffer(view->active_buffer); @@ -38,19 +38,6 @@ View *Command_ExecHidden(String buffer_name, String cmd, String working_dir) { return view; } -// void Command_Exec(String cmd) { -// BSet main = GetActiveMainSet(); -// Window *next_window = GetNextLayoutWindow(main.window); -// BSet set = GetBSet(next_window); -// CheckpointBeforeGoto(set.window); - -// String working_dir = Command_GetDir(); -// Exec(NullViewID, true, cmd, working_dir); - -// set.window->active_view = NullViewID; -// ActiveWindow = set.window->id; -// } - BSet Command_BeginConsoleJump() { BSet main = GetActiveMainSet(); CheckpointBeforeGoto(main.window); @@ -138,15 +125,24 @@ int Lua_C(lua_State *L) { return 0; } -int Lua_Eval(lua_State *L) { - String string = lua_tostring(L, 1); - lua_pop(L, 1); - +void Command_Eval(String string) { if (luaL_dostring(LuaState, string.data) != LUA_OK) { const char *error_message = lua_tostring(LuaState, -1); ReportWarningf("Execution error! %s", error_message); lua_pop(LuaState, 1); } +} + +void Command_Eval(String16 string) { + Scratch scratch; + Command_Eval(ToString(scratch, string)); +} + +int Lua_Eval(lua_State *L) { + String string = lua_tostring(L, 1); + lua_pop(L, 1); + Command_Eval(string); + return 0; } @@ -257,8 +253,7 @@ int Lua_SetProjectFile(lua_State *L) { } int Lua_Reopen(lua_State *L) { - BSet main = GetActiveMainSet(); - ReopenBuffer(main.view, main.buffer); + ReopenBuffer(GetActiveMainSet()); return 0; } diff --git a/src/text_editor/management.cpp b/src/text_editor/management.cpp index b922fa2..db1bf22 100644 --- a/src/text_editor/management.cpp +++ b/src/text_editor/management.cpp @@ -16,21 +16,34 @@ WindowID ActiveWindow; WindowID ScrollbarSelected = {-1}; WindowID DocumentSelected = {-1}; -Range DocumentRangeAnchor; +Caret DocumentAnchor; Buffer *LuaProjectBuffer; Buffer *LuaConfigBuffer; Buffer *GCInfoBuffer; Buffer *EventBuffer; +RandomSeed UniqueBufferNameSeed = {}; +String GetUniqueBufferName(String working_dir, String prepend_name) { + if (UniqueBufferNameSeed.a == 0) { + double value = get_time_in_micros(); + UniqueBufferNameSeed.a = *(uint64_t *)&value; + } + Scratch scratch; + uint64_t number = GetRandomU64(&UniqueBufferNameSeed); + String buffer_name = Format(scratch, "%.*s/%.*s%llu.log", FmtString(working_dir), FmtString(prepend_name), number); + buffer_name = Intern(&GlobalInternTable, buffer_name); + return buffer_name; +} + void InitScratchBuffer() { Allocator sys_allocator = GetSystemAllocator(); - Buffer *null_buffer = CreateBuffer(sys_allocator, BuffCWD("+console")); + Buffer *null_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "console")); View *null_view = CreateView(null_buffer->id); Assert(null_buffer->id == NullBufferID && null_view->id == NullViewID); - GCInfoBuffer = CreateBuffer(sys_allocator, BuffCWD("+gc")); - EventBuffer = CreateBuffer(sys_allocator, BuffCWD("+events")); + GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "gc")); + EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "events")); EventBuffer->no_history = true; } @@ -86,13 +99,6 @@ inline View *GetView(ViewID id) { inline bool IsNull(Buffer *buffer) { return buffer->id.id == NullBufferID.id; } inline Window *GetActiveWindow() { return GetWindow(ActiveWindow); } -String BuffCWD(String string) { - Scratch scratch; - String result = Format(scratch, "%.*s/%.*s", FmtString(WorkingDir), FmtString(string)); - result = Intern(&GlobalInternTable, result); - return result; -} - void InitBuffer(Allocator allocator, Buffer *buffer, String name, Int size = 4096) { buffer->id = AllocBufferID(buffer); buffer->name = Intern(&GlobalInternTable, name); @@ -231,13 +237,6 @@ BSet GetActiveTitleSet() { return GetBSet(window); } -RandomSeed UniqueBufferNameSeed = {13}; -String GetUniqueBufferName(Allocator allocator, String working_dir, String prepend_name) { - uint64_t number = GetRandomU64(&UniqueBufferNameSeed); - String buffer_name = Format(allocator, "%.*s/%.*s%llu", FmtString(working_dir), FmtString(prepend_name), number); - return buffer_name; -} - String Command_GetFilename() { BSet set = GetActiveMainSet(); return set.buffer->name; @@ -303,13 +302,18 @@ String16 ToUnixString16(Allocator allocator, String string_) { return string; } -void ReopenBuffer(View *view, Buffer *buffer) { +void ReopenBuffer(BSet set) { Scratch scratch; - String string = ReadFile(scratch, buffer->name); - if (string.len == 0) return; + String string = ReadFile(scratch, set.buffer->name); + if (string.len == 0) { + return; + } + String16 string16 = ToUnixString16(scratch, string); - Command_ReplaceWithoutMovingCarets(view, GetRange(buffer), string16); - buffer->file_mod_time = GetFileModTime(buffer->name); + Command_ReplaceWithoutMovingCarets(set.view, GetRange(set.buffer), string16); + set.buffer->file_mod_time = GetFileModTime(set.buffer->name); + set.buffer->changed_on_disk = false; + ActiveWindow = set.window->id; } // This function as name suggests tries to open a buffer, @@ -334,7 +338,7 @@ Buffer *BufferOpenFile(String path) { if (!FileExists(path)) { buffer = CreateBuffer(sys_allocator, path); } else if (IsDir(path)) { - String buffer_name = GetUniqueBufferName(scratch, path, "+dir-"); + String buffer_name = GetUniqueBufferName(path, "+dir-"); buffer = CreateBuffer(sys_allocator, buffer_name, 4096 * 2); RawAppendf(buffer, "..\n"); @@ -445,6 +449,15 @@ void GarbageCollect() { // } // } + For(Buffers) { + Buffer *buffer = GetBuffer(it); + if (buffer->file_mod_time) { + int64_t new_file_mod_time = GetFileModTime(buffer->name); + if (buffer->file_mod_time != new_file_mod_time) { + buffer->changed_on_disk = true; + } + } + } // IterRemove(Buffers) { // IterRemovePrepare(Buffers); // Buffer *buffer = it.o; diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index addcf3d..b174eab 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -222,7 +222,7 @@ Array GetEventsForFrame(Allocator allocator) { void Windows_SetupVCVarsall(mco_coro *co) { Scratch scratch; String working_dir = Command_GetDir(); - String buffer_name = GetUniqueBufferName(scratch, working_dir, "+cmd-"); + String buffer_name = GetUniqueBufferName(working_dir, "+cmd-"); String cmd = Format(scratch, "\"%.*s\" && set", FmtString(StyleVCVarsall)); View *view = Command_ExecHidden(buffer_name, cmd, working_dir); for (;;) { diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index 3d72d54..1671748 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -79,8 +79,6 @@ String ExeDir; Arena Perm; float DPIScale = 1.0f; -bool EvalString(Allocator allocator, String16 string16); -bool Command_EvalLua(View *view, String16 string); Rect2I GetVisibleCells(Window *window); void AfterEdit(View *view, Array edits); Scroller ComputeScrollerRect(Window *window); @@ -95,6 +93,8 @@ void Command_Append(View *view, String16 string, bool scroll_to_end_if_cu void Command_Append(View *view, String string, bool scroll_to_end_if_cursor_on_last_line); Array Command_ReplaceEx(Allocator scratch, View *view, String16 string); void Command_ReplaceWithoutMovingCarets(View *view, Range range, String16 string); +void Command_Eval(String string); +void Command_Eval(String16 string); void Command_Copy(View *view); void Command_Paste(View *view); @@ -104,7 +104,6 @@ void ReportErrorf(const char *fmt, ...); void ReportWarningf(const char *fmt, ...); void Command_Appendf(View *view, const char *fmt, ...); -String BuffCWD(String string); Buffer *CreateBuffer(Allocator allocator, String name, Int size = 4096); View *CreateView(BufferID active_buffer); diff --git a/src/text_editor/title_bar.cpp b/src/text_editor/title_bar.cpp index fe21024..e2b940d 100644 --- a/src/text_editor/title_bar.cpp +++ b/src/text_editor/title_bar.cpp @@ -47,7 +47,7 @@ void ReplaceTitleBarData(Window *window) { AdjustCarets(edits, &caret_copy); } - char *reopen = main.buffer->changed_on_disk ? " #Reopen()" : ""; + char *reopen = main.buffer->changed_on_disk ? " Reopen()" : ""; String s = Format(scratch, "%.*s:%lld:%lld%s", FmtString(main.buffer->name), (long long)xy.line + 1ll, (long long)xy.col + 1ll, reopen); String16 string = ToString16(scratch, s); String16 string_to_replace = GetString(title.buffer, replace_range); diff --git a/src/text_editor/todo.txt b/src/text_editor/todo.txt index 1548516..661c8a2 100644 --- a/src/text_editor/todo.txt +++ b/src/text_editor/todo.txt @@ -1,5 +1,4 @@ -- maybe commands should mostly be dumped into a single buffer -- When moving last line alt + arrow key it moves it into upper line, super annoying +!!As little lua code as possible, but lua code should be powerful just in case of quick edits - maybe we could allow user to change window titles which would make them special in some way. A:/text_editor/+test_buffer:1:1:ADE | -------------- @@ -12,10 +11,9 @@ activate_buffer - LoadWord, EncloseWord configurable? - dump text editor state to file, restore state - help menu popup when for example in process buffer, on tile bar buffer and stuff like that -- shift click inside selection should move the selection -- shift click larger then screen jumps the view to other caret - report errors (try showing a window) - proper lister +- revamp windows/layout/resize - 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 | we could just show ForceClose() in the titlebar @@ -26,25 +24,13 @@ activate_buffer - A lister which is going to show project without the full path and sorted by recency - word complete - Search all buffers in 10X style, incrementally searched results popping up on every key press (maybe we need coroutine library in C so this is easier?) -- To implement that I think it would be best to load all files into memory - kill view - killing all views for buffer ejects buffer (maybe also introduce kill buffer) -- ask if you want to close without saving on exit - ask if you want to create new file? -- Cmd should reuse the window which already has the build - escapeing multiple cursor after ctrl + d should put the cursor where it was (probably will need to swap secondary and primary cursor for new cursor - draw indentation levels like in sublime (those lines) - we render chars one by one so seems relatively easy to figure out if whitespace belongs to beginning of line (make sure to add max value like 40 because of big files) - code sections, visual demarkation if beginning of line has a very specific text + goto next / goto prev section hotkey! -- change size of command window because it's wacky - combine glyph and selection rendering -- shift + ctrl + click should open a new window and then with alt it probably should kill it - - layouting, resize windows - - try to incorporate the acme square which allows you to put windows wherever and also scale the border -BUG: there is a click hang when switching windows sometimes, you click after select and it doesn't switch active window - -- PageUp for some reason stops at 2 line before last line -- page up and down should also scroll and leave you in exactly same scroll - backlog - expose a coroutine based scripting enviorment where user can execute shell commands wait for them and perform actions in very linear manner - Test stdin writing code diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index 4341534..d6f94f2 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -217,7 +217,7 @@ void InitWindows() { Window *window = CreateWindow(); WindowID window_id = window->id; window->is_column = true; - Buffer *buffer = CreateBuffer(sys_allocator, BuffCWD("test_buffer")); + Buffer *buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "test_buffer")); View *view = CreateView(buffer->id); LoadTestBufferMessage(buffer); window->active_view = view->id; @@ -235,7 +235,7 @@ void InitWindows() { window->visible = false; window->z = 2; - Buffer *buffer = CreateBuffer(sys_allocator, BuffCWD("+debug")); + Buffer *buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "debug")); DebugBufferID = buffer->id; buffer->no_history = true;