Compare commits

..

3 Commits

Author SHA1 Message Date
krzosa
2acf2c189c First prototype of coroutine based UI 2025-12-28 16:12:22 +01:00
krzosa
06cb073832 New UI buffer thing 2025-12-28 10:29:53 +01:00
krzosa
00442da5dd Misc improvements 2025-12-28 10:29:05 +01:00
17 changed files with 250 additions and 108 deletions

View File

@@ -3,12 +3,17 @@
Use session 1: Use session 1:
- OpenCommand in command window freezes the app - OpenCommand in command window freezes the app
- Shift + backspace should delete normally
- SDL popups are not working on linux ... - SDL popups are not working on linux ...
- Creating files more efficiently - CloseAll idea: should create a buffer interface with list of buffers, user would be able to select which buffers to save and which not, then button UICloseAll
- Creating files more efficiently, renaming
- Dialog popup on save? Or ctrl-shift-s? - Dialog popup on save? Or ctrl-shift-s?
- Maybe rename in bar and do :Rename - Maybe rename in bar and do :Rename
New UI Session
- Cleanup String16/String with Open and EvalCommands after lua refactor
- Uneditable buffers ?
- Maybe marked allocations??? So that we can associate allocations with a buffer or view and then dealloc all at the same time
- Open with seek string (open at pattern) filename:32 filename:/^Window$/ - Open with seek string (open at pattern) filename:32 filename:/^Window$/
- build console window - build console window
- Show what process/coroutines are running and allow to kill (active process buffer?) - Show what process/coroutines are running and allow to kill (active process buffer?)

View File

@@ -66,6 +66,16 @@
#define COMPILER_GCC 0 #define COMPILER_GCC 0
#endif #endif
#ifndef DEBUG_BUILD
#define DEBUG_BUILD 1
#endif
#if DEBUG_BUILD
#define IF_DEBUG(x) x
#else
#define IF_DEBUG(x)
#endif
#if OS_WINDOWS #if OS_WINDOWS
#define BREAK() __debugbreak() #define BREAK() __debugbreak()
#elif OS_LINUX #elif OS_LINUX
@@ -84,7 +94,7 @@ EM_JS(void, JS_Breakpoint, (), {
BREAK(); \ BREAK(); \
} }
#define InvalidCodepath() Assert(!"invalid codepath") #define InvalidCodepath() Assert(!"invalid codepath")
#define ElseInvalidCodepath() else {InvalidCodepath()} #define ElseInvalidCodepath() else {InvalidCodepath();}
#define KiB(x) ((x##ull) * 1024ull) #define KiB(x) ((x##ull) * 1024ull)
#define MiB(x) (KiB(x) * 1024ull) #define MiB(x) (KiB(x) * 1024ull)

View File

@@ -186,6 +186,7 @@ void BeginFrameRender(float wx, float wy) {
// ---------- EndFrameRender for ES3 ---------- // ---------- EndFrameRender for ES3 ----------
void EndFrameRender(float wx, float wy, Color color) { void EndFrameRender(float wx, float wy, Color color) {
ProfileFunction();
glEnable(GL_BLEND); glEnable(GL_BLEND);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

View File

@@ -152,5 +152,6 @@ void Test(mco_coro *co) {
void InitTests() { void InitTests() {
ConfigWaitForEvents = false; ConfigWaitForEvents = false;
TestDir = Format(TestArena, "%S/test_env", GetExeDir(TestArena)); TestDir = Format(TestArena, "%S/test_env", GetExeDir(TestArena));
CoAdd(Test); CoData *data = CoAdd(Test);
data->dont_wait_until_resolved = true;
} }

View File

@@ -1506,9 +1506,9 @@ String16 ToUnixString16(Allocator allocator, String string_) {
Buffer *BufferOpenFile(String path) { Buffer *BufferOpenFile(String path) {
ProfileFunction(); ProfileFunction();
Allocator sys_allocator = GetSystemAllocator(); Allocator sys_allocator = GetSystemAllocator();
Scratch scratch; Scratch scratch;
path = GetAbsolutePath(scratch, path); path = GetAbsolutePath(scratch, path);
Buffer *buffer = GetBuffer(path); Buffer *buffer = GetBuffer(path);
if (!IsNull(buffer) || (IsNull(buffer) && buffer->name == path)) { if (!IsNull(buffer) || (IsNull(buffer) && buffer->name == path)) {
return buffer; return buffer;
@@ -1519,10 +1519,11 @@ Buffer *BufferOpenFile(String path) {
} else if (IsDir(path)) { } else if (IsDir(path)) {
buffer = CreateBuffer(sys_allocator, path); buffer = CreateBuffer(sys_allocator, path);
buffer->is_dir = true; buffer->is_dir = true;
buffer->garbage = true;
} else { } else {
String string = ReadFile(scratch, path); String string = ReadFile(scratch, path);
buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096); buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096);
buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap); buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap);
buffer->file_mod_time = GetFileModTime(path); buffer->file_mod_time = GetFileModTime(path);
UpdateLines(buffer, {}, String16{(char16_t *)buffer->data, buffer->len}); UpdateLines(buffer, {}, String16{(char16_t *)buffer->data, buffer->len});
} }

View File

@@ -41,17 +41,6 @@ void JumpGarbageBuffer(BSet *set, String buffer_name = "") {
set->buffer->garbage = true; set->buffer->garbage = true;
} }
void BeginJump(BSet *set, BufferID buffer_id = NullBufferID) {
set->buffer = GetBuffer(buffer_id);
set->view = WindowOpenBufferView(set->window, set->buffer->name);
}
void EndJump(BSet set) {
Int pos = XYToPos(set.buffer, {0, set.buffer->line_starts.len - 1});
set.view->carets[0] = MakeCaret(pos);
UpdateScroll(set.window, true);
}
void MouseLoadWord(Event event, String meta = "") { void MouseLoadWord(Event event, String meta = "") {
Vec2I mouse = MouseVec2I(); Vec2I mouse = MouseVec2I();
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
@@ -637,6 +626,8 @@ BSet Open(Window *window, String path, String meta, bool set_active = true) {
} else if (o.kind == OpenKind_BackgroundExec) { } else if (o.kind == OpenKind_BackgroundExec) {
// this shouldn't change the focus/window/view // this shouldn't change the focus/window/view
Exec(NullViewID, true, o.path, GetMainDir()); Exec(NullViewID, true, o.path, GetMainDir());
} else if (o.kind == OpenKind_Command) {
EvalCommand(o.path);
} else if (o.kind == OpenKind_Skip) { } else if (o.kind == OpenKind_Skip) {
return {}; return {};
} else { } else {
@@ -704,7 +695,7 @@ void Command_SetWorkDir() {
WorkDir = GetDir(main.buffer); WorkDir = GetDir(main.buffer);
} RegisterCommand(Command_SetWorkDir, ""); } RegisterCommand(Command_SetWorkDir, "");
String CodeSkipPatterns[] = {".git/"}; String CodeSkipPatterns[] = {".git/", ".obj", ".o", ".pdb", ".exe"};
String Coro_OpenCodeDir; String Coro_OpenCodeDir;
void Coro_OpenCode(mco_coro *co) { void Coro_OpenCode(mco_coro *co) {
@@ -739,7 +730,8 @@ void Coro_OpenCode(mco_coro *co) {
void OpenCode(String dir) { void OpenCode(String dir) {
Coro_OpenCodeDir = dir; Coro_OpenCodeDir = dir;
CoAdd(Coro_OpenCode); CoData *data = CoAdd(Coro_OpenCode);
data->dont_wait_until_resolved = true;
} }
void Command_OpenCode() { void Command_OpenCode() {
@@ -756,6 +748,9 @@ void Command_CloseWindow() {
} RegisterCommand(Command_CloseWindow, ""); } RegisterCommand(Command_CloseWindow, "");
SaveResult TrySavingBuffer(Buffer *buffer) { SaveResult TrySavingBuffer(Buffer *buffer) {
if (buffer->special || buffer->garbage) {
return SAVE_NO;
}
if (buffer->dirty) { if (buffer->dirty) {
SaveResult save = SaveMessageBox(buffer->name); SaveResult save = SaveMessageBox(buffer->name);
if (save == SAVE_CANCEL) { if (save == SAVE_CANCEL) {
@@ -787,15 +782,13 @@ SaveResult TrySavingAllBuffers() {
return SAVE_YES; return SAVE_YES;
} }
void Command_Close() { void Coro_Close(mco_coro *co) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
if (TrySavingBuffer(main.buffer) == SAVE_CANCEL) { if (main.buffer->special || main.buffer->garbage) {
Close(main.view->id);
return; return;
} }
main.window->active_view = FindInactiveView();
Close(main.view->id);
bool ref = false; bool ref = false;
For (Views) { For (Views) {
if (it->id == main.view->id) { if (it->id == main.view->id) {
@@ -807,9 +800,56 @@ void Command_Close() {
} }
} }
if (!ref) { if (ref) {
Close(main.buffer->id); Close(main.view->id);
return;
} }
if (!main.buffer->dirty) {
Close(main.buffer->id);
return;
}
Buffer *buffer = main.buffer;
JumpGarbageBuffer(&main);
NextActiveWindowID = main.window->id;
RawAppendf(main.buffer, R"==(
Do you want to save [%S] before closing?
:Yes :No :Cancel
)==", buffer->name);
main.view->carets[0] = FindNext(main.buffer, u":Yes", MakeCaret(0));
main.view->carets[0].range.min = main.view->carets[0].range.max;
Add(&main.view->hooks, {"Yes", "enter", [](){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Yes";}, ParseKeyCached("enter")});
Add(&main.view->hooks, {"No", "", [](){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "No";}, ParseKeyCached("")});
Add(&main.view->hooks, {"Cancel", "escape", [](){BSet active = GetBSet(ActiveWindowID); active.view->hook_cmd = "Cancel";}, ParseKeyCached("escape")});
for (;;) {
if (main.window->active_view != main.view->id || main.window->close) {
Close(main.buffer->id);
return;
}
if (main.view->hook_cmd != "") {
break;
}
CoYield(co);
}
Close(main.buffer->id);
if (main.view->hook_cmd == "Yes") {
SaveBuffer(buffer);
Close(buffer->id);
} else if (main.view->hook_cmd == "No") {
Close(buffer->id);
} else if (main.view->hook_cmd == "Cancel") {
return;
} ElseInvalidCodepath();
}
void Command_Close() {
CoAdd(Coro_Close);
} RegisterCommand(Command_Close, "ctrl-w"); } RegisterCommand(Command_Close, "ctrl-w");
void Command_Quit() { void Command_Quit() {
@@ -835,17 +875,17 @@ void Command_CloseAll() {
} }
} RegisterCommand(Command_CloseAll, ""); } RegisterCommand(Command_CloseAll, "");
void Command_GotoBackward() { void Command_JumpBack() {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
main.window->skip_checkpoint = true; main.window->skip_checkpoint = true;
GotoBackward(main.window); JumpBack(main.window);
} RegisterCommand(Command_GotoBackward, "alt-q | mousex1"); } RegisterCommand(Command_JumpBack, "alt-q | mousex1");
void Command_GotoForward() { void Command_JumpForward() {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
main.window->skip_checkpoint = true; main.window->skip_checkpoint = true;
GotoForward(main.window); JumpForward(main.window);
} RegisterCommand(Command_GotoForward, "alt-shift-q | mousex2"); } RegisterCommand(Command_JumpForward, "alt-shift-q | mousex2");
void Command_OpenUpFolder() { void Command_OpenUpFolder() {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
@@ -1080,7 +1120,7 @@ void Command_SelectToLineEnd() {
void Command_Delete() { void Command_Delete() {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
Delete(active.view, DIR_LEFT); Delete(active.view, DIR_LEFT);
} RegisterCommand(Command_Delete, "backspace"); } RegisterCommand(Command_Delete, "shift-backspace | backspace");
void Command_DeleteBoundary() { void Command_DeleteBoundary() {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
@@ -1090,7 +1130,7 @@ void Command_DeleteBoundary() {
void Command_DeleteForward() { void Command_DeleteForward() {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
Delete(active.view, DIR_RIGHT); Delete(active.view, DIR_RIGHT);
} RegisterCommand(Command_DeleteForward, "delete"); } RegisterCommand(Command_DeleteForward, "shift-delete | delete");
void Command_DeleteForwardBoundary() { void Command_DeleteForwardBoundary() {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);

View File

@@ -102,4 +102,4 @@ void Command_Cut() {
SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets); SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets);
ClipboardCopy(active.view); ClipboardCopy(active.view);
Replace(active.view, u""); Replace(active.view, u"");
} RegisterCommand(Command_Cut, "ctrl-x"); } RegisterCommand(Command_Cut, "ctrl-x");

View File

@@ -157,6 +157,32 @@ Trigger *ParseKey(Allocator allocator, String key, char *debug_name) {
return result; return result;
} }
struct CachedTrigger {
Trigger *trigger;
String key;
};
Array<CachedTrigger> CachedTriggers;
Trigger *ParseKeyCached(String key) {
if (key.len == 0) {
return NULL;
}
For (CachedTriggers) {
if (it.key == key) {
return it.trigger;
}
}
Allocator allocator = GetSystemAllocator();
Trigger *result = ParseKey(allocator, key, key.data);
if (!result) {
return NULL;
}
Add(&CachedTriggers, {result, key});
return result;
}
bool MatchEvent(Trigger *trigger, Event *event) { bool MatchEvent(Trigger *trigger, Event *event) {
if (trigger->kind == TriggerKind_Key) { if (trigger->kind == TriggerKind_Key) {
if (trigger->key == event->key && trigger->ctrl == event->ctrl && trigger->alt == event->alt && trigger->shift == event->shift) { if (trigger->key == event->key && trigger->ctrl == event->ctrl && trigger->alt == event->alt && trigger->shift == event->shift) {

View File

@@ -11,7 +11,7 @@ void CoRemove(String name) {
} }
#define CoAdd(x) CoAddEx(x, #x) #define CoAdd(x) CoAddEx(x, #x)
mco_coro *CoAddEx(CoroutineProc *proc, String name) { CoData *CoAddEx(CoroutineProc *proc, String name) {
CoRemove(name); CoRemove(name);
mco_desc desc = mco_desc_init(proc, 0); mco_desc desc = mco_desc_init(proc, 0);
@@ -24,7 +24,7 @@ mco_coro *CoAddEx(CoroutineProc *proc, String name) {
mco_resume(coro); mco_resume(coro);
Add(&ActiveCoroutines, {coro, name}); Add(&ActiveCoroutines, {coro, name});
return coro; return GetLast(ActiveCoroutines);
} }
void CoUpdate(Event *event) { void CoUpdate(Event *event) {
@@ -46,6 +46,8 @@ void CoUpdate(Event *event) {
ReportWarningf("failed to resume coroutine %d", ok); ReportWarningf("failed to resume coroutine %d", ok);
mco_destroy(it.co); mco_destroy(it.co);
remove_item = true; remove_item = true;
} else {
it.dont_wait_until_resolved = true;
} }
} }
} }
@@ -62,7 +64,7 @@ Event *CoYield(mco_coro *co) {
Assert(ok == MCO_SUCCESS); Assert(ok == MCO_SUCCESS);
Event *event = NULL; Event *event = NULL;
ok = mco_pop(co, &event, sizeof(Event *)); ok = mco_pop(co, &event, sizeof(Event *));
Assert(ok == MCO_SUCCESS); Assert(ok == MCO_SUCCESS);
return event; return event;

View File

@@ -79,7 +79,7 @@ String Intern(InternTable *table, String string) {
// optimize worst offenders (like event text) // optimize worst offenders (like event text)
InternTable GlobalInternTable; InternTable GlobalInternTable;
Function *LastExecutedCommand; Function *LastExecutedManualCommand;
Array<CommandData> CommandFunctions; Array<CommandData> CommandFunctions;
Array<FunctionData> TestFunctions; Array<FunctionData> TestFunctions;
Array<Variable> Variables; Array<Variable> Variables;
@@ -87,7 +87,7 @@ Array<Variable> Variables;
Array<Process> ActiveProcesses = {}; Array<Process> ActiveProcesses = {};
Array<String> ProcessEnviroment = {}; Array<String> ProcessEnviroment = {};
struct CoData { mco_coro *co; String name; }; struct CoData { mco_coro *co; String name; bool dont_wait_until_resolved; };
Array<CoData> ActiveCoroutines; Array<CoData> ActiveCoroutines;
@@ -162,5 +162,5 @@ RegisterVariable(String, ConfigFont, "/home/krz/text_editor/package/CascadiaMono
RegisterVariable(String, ConfigVCVarsall, "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat"); RegisterVariable(String, ConfigVCVarsall, "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat");
RegisterVariable(Float, ConfigUndoMergeTimeWindow, 0.3); RegisterVariable(Float, ConfigUndoMergeTimeWindow, 0.3);
RegisterVariable(Float, ConfigJumpHistoryMergeTimeWindow, 0.3); RegisterVariable(Float, ConfigJumpHistoryMergeTimeWindow, 0.3);
RegisterVariable(Int, ConfigJumpHistorySize, 512); RegisterVariable(Int, ConfigJumpHistorySize, 4096);
RegisterVariable(String, ConfigInternetBrowser, "firefox"); RegisterVariable(String, ConfigInternetBrowser, "firefox");

View File

@@ -78,6 +78,7 @@ void SetMouseCursor(SDL_SystemCursor id) {
#endif #endif
void SetMouseCursor(Event event) { void SetMouseCursor(Event event) {
ProfileFunction();
Scratch scratch; Scratch scratch;
Array<Window *> order = GetWindowZOrder(scratch); Array<Window *> order = GetWindowZOrder(scratch);
Vec2I mouse = MouseVec2I(); Vec2I mouse = MouseVec2I();
@@ -386,11 +387,24 @@ void OnCommand(Event event) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
For (CommandFunctions) { bool executed = false;
For (active.view->hooks) {
if (it.trigger && MatchEvent(it.trigger, &event)) { if (it.trigger && MatchEvent(it.trigger, &event)) {
ProfileScopeEx(it.name); ProfileScopeEx(it.name);
it.function(); it.function();
LastExecutedCommand = it.function; LastExecutedManualCommand = it.function;
executed = true;
break;
}
}
if (executed == false) {
For (CommandFunctions) {
if (it.trigger && MatchEvent(it.trigger, &event)) {
ProfileScopeEx(it.name);
it.function();
LastExecutedManualCommand = it.function;
}
} }
} }
@@ -412,6 +426,29 @@ void OnCommand(Event event) {
IF_DEBUG(AssertRanges(active.view->carets)); IF_DEBUG(AssertRanges(active.view->carets));
} }
void EvalCommand(String command) {
BSet active = GetBSet(ActiveWindowID);
For (active.view->hooks) {
if (it.name == command) {
ProfileScopeEx(it.name);
it.function();
return;
}
}
For (CommandFunctions) {
if (it.name == command) {
ProfileScopeEx(it.name);
it.function();
return;
}
}
}
void EvalCommand(String16 command) {
Scratch scratch;
EvalCommand(ToString(scratch, command));
}
void GarbageCollect() { void GarbageCollect() {
if (RunGCThisFrame == false) { if (RunGCThisFrame == false) {
return; return;
@@ -438,7 +475,11 @@ void GarbageCollect() {
InvalidCodepath(); InvalidCodepath();
} }
Buffer *buffer = GetBuffer(it->active_buffer); Buffer *buffer = GetBuffer(it->active_buffer, NULL);
if (buffer == NULL || buffer->close) {
it->close = true;
}
if (!it->close) { if (!it->close) {
if (!buffer->garbage) { if (!buffer->garbage) {
continue; continue;
@@ -450,10 +491,9 @@ void GarbageCollect() {
} }
} }
RawAppendf(GCInfoBuffer, "View %d %S\n", (int)it->id.id, buffer->name); RawAppendf(GCInfoBuffer, "View %d %S\n", (int)it->id.id, buffer ? buffer->name : String{"NULL"});
remove_item = true; remove_item = true;
Dealloc(&it->carets); Dealloc(it);
Dealloc(sys_allocator, it);
} }
IterRemove(Buffers) { IterRemove(Buffers) {
@@ -491,6 +531,11 @@ void GarbageCollect() {
Dealloc(&it->goto_redo); Dealloc(&it->goto_redo);
Dealloc(sys_allocator, it); Dealloc(sys_allocator, it);
remove_item = true; remove_item = true;
} else {
View *view = FindView(it->active_view, NULL);
if (!view) {
JumpToLastValidView(it);
}
} }
} }
} }
@@ -637,8 +682,17 @@ void MainLoop() {
Update(it); Update(it);
} }
bool dont_wait_until_resolved = false;
For (ActiveCoroutines) {
if (it.dont_wait_until_resolved) {
dont_wait_until_resolved = true;
break;
}
}
WaitForEvents = ConfigWaitForEvents; WaitForEvents = ConfigWaitForEvents;
if (IsDocumentSelectionValid() || IsScrollbarSelectionValid() || ActiveProcesses.len || ActiveCoroutines.len) { if (IsDocumentSelectionValid() || IsScrollbarSelectionValid() || ActiveProcesses.len || dont_wait_until_resolved) {
WaitForEvents = false; WaitForEvents = false;
} }
@@ -787,7 +841,7 @@ int main(int argc, char **argv)
For (CommandFunctions) { For (CommandFunctions) {
if (it.binding.len != 0) { if (it.binding.len != 0) {
it.trigger = ParseKey(Perm, it.binding, it.name.data); it.trigger = ParseKeyCached(it.binding);
} }
} }
@@ -811,7 +865,8 @@ int main(int argc, char **argv)
ReportConsolef("WorkDir = %S", WorkDir); ReportConsolef("WorkDir = %S", WorkDir);
if (Testing) InitTests(); if (Testing) InitTests();
#if OS_WINDOWS #if OS_WINDOWS
CoAdd(Windows_SetupVCVarsall); CoData *co_data = CoAdd(Windows_SetupVCVarsall);
co_data->dont_wait_until_resolved = true;
#endif #endif
#if OS_WASM #if OS_WASM
emscripten_set_main_loop(MainLoop, 0, 1); emscripten_set_main_loop(MainLoop, 0, 1);

View File

@@ -103,6 +103,8 @@ Buffer *CreateBuffer(Allocator allocator, String name, Int size = 4096);
View *CreateView(BufferID active_buffer); View *CreateView(BufferID active_buffer);
void ReopenBuffer(Buffer *buffer); void ReopenBuffer(Buffer *buffer);
bool ProcessIsActive(ViewID view); bool ProcessIsActive(ViewID view);
void EvalCommand(String command);
void EvalCommand(String16 command);
inline bool operator==(BufferID a, BufferID b) { return a.id == b.id; } inline bool operator==(BufferID a, BufferID b) { return a.id == b.id; }
inline bool operator==(ViewID a, ViewID b) { return a.id == b.id; } inline bool operator==(ViewID a, ViewID b) { return a.id == b.id; }
@@ -120,17 +122,7 @@ inline bool operator!=(ViewID a, ViewID b) { return a.id != b.id; }
// We don't really care about opening buffers that don't have proper paths // We don't really care about opening buffers that don't have proper paths
Buffer *BufferOpenFile(String path); Buffer *BufferOpenFile(String path);
#if DEBUG_BUILD
#define IF_DEBUG(x) x
#else
#define IF_DEBUG(x)
#endif
typedef void Function();
typedef void PFunction(void *param); typedef void PFunction(void *param);
struct FunctionData { String name; Function *function; };
struct CommandData { String name; String binding; Function *function; struct Trigger *trigger; };
struct PFunctionData { String name; PFunction *function; }; struct PFunctionData { String name; PFunction *function; };
struct Register_Function { struct Register_Function {

View File

@@ -8,11 +8,18 @@ API View *CreateView(BufferID active_buffer) {
view->id = AllocViewID(view); view->id = AllocViewID(view);
view->active_buffer = active_buffer; view->active_buffer = active_buffer;
view->carets.allocator = al; view->carets.allocator = al;
view->hooks.allocator = al;
Add(&view->carets, {0, 0}); Add(&view->carets, {0, 0});
Add(&Views, view); Add(&Views, view);
return view; return view;
} }
void Dealloc(View *view) {
Dealloc(&view->carets);
Dealloc(&view->hooks);
Dealloc(view->carets.allocator, view);
}
API View *FindView(ViewID view_id, View *default_view) { API View *FindView(ViewID view_id, View *default_view) {
For(Views) { For(Views) {
if (it->id == view_id) { if (it->id == view_id) {

View File

@@ -1,6 +1,10 @@
struct View; struct View;
struct ViewID { Int id; View *o; }; struct ViewID { Int id; View *o; };
typedef void Function();
struct FunctionData { String name; Function *function; };
struct CommandData { String name; String binding; Function *function; struct Trigger *trigger; };
struct View { struct View {
ViewID id; ViewID id;
BufferID active_buffer; BufferID active_buffer;
@@ -11,6 +15,8 @@ struct View {
Caret main_caret_on_begin_frame; Caret main_caret_on_begin_frame;
bool update_scroll; bool update_scroll;
String hook_cmd;
Array<CommandData> hooks;
String16 prev_search_line; String16 prev_search_line;
struct { struct {
unsigned close : 1; unsigned close : 1;

View File

@@ -235,7 +235,7 @@ Int ScreenSpaceToBufferPosErrorOutOfBounds(Window *window, View *view, Buffer *b
return result; return result;
} }
GotoCrumb GetCrumb(Array<GotoCrumb> *cr) { GotoCrumb PopCrumb(Array<GotoCrumb> *cr) {
for (; cr->len;) { for (; cr->len;) {
GotoCrumb c = Pop(cr); GotoCrumb c = Pop(cr);
View *view = FindView(c.view_id, NULL); View *view = FindView(c.view_id, NULL);
@@ -246,13 +246,33 @@ GotoCrumb GetCrumb(Array<GotoCrumb> *cr) {
return {}; return {};
} }
void GotoBackward(Window *window) { View *GetLastValidView(Window *window) {
For (IterateInReverse(&window->goto_redo)) {
if (it.view_id == window->active_view) continue;
View *view = FindView(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);
if (view) return view;
}
return Views[0];
}
View *JumpToLastValidView(Window *window) {
View *view = GetLastValidView(window);
window->active_view = view->id;
return view;
}
void JumpBack(Window *window) {
if (window->jump_history == false) return; if (window->jump_history == false) return;
if (window->goto_history.len <= 0) return; if (window->goto_history.len <= 0) return;
BSet set = GetBSet(window); BSet set = GetBSet(window);
Add(&window->goto_redo, {set.view->id, set.view->carets[0], GetTimeSeconds()}); Add(&window->goto_redo, {set.view->id, set.view->carets[0], GetTimeSeconds()});
GotoCrumb c = GetCrumb(&window->goto_history); GotoCrumb c = PopCrumb(&window->goto_history);
window->active_view = c.view_id; window->active_view = c.view_id;
View *view = GetView(c.view_id); View *view = GetView(c.view_id);
view->carets[0] = c.caret; view->carets[0] = c.caret;
@@ -261,18 +281,18 @@ void GotoBackward(Window *window) {
if (window->goto_history.len) { if (window->goto_history.len) {
GotoCrumb *next = GetLast(window->goto_history); GotoCrumb *next = GetLast(window->goto_history);
if (c.view_id == next->view_id && c.time - next->time <= ConfigJumpHistoryMergeTimeWindow) { if (c.view_id == next->view_id && c.time - next->time <= ConfigJumpHistoryMergeTimeWindow) {
GotoBackward(window); JumpBack(window);
} }
} }
} }
void GotoForward(Window *window) { void JumpForward(Window *window) {
if (window->jump_history == false) return; if (window->jump_history == false) return;
if (window->goto_redo.len <= 0) return; if (window->goto_redo.len <= 0) return;
BSet set = GetBSet(window); BSet set = GetBSet(window);
Add(&window->goto_history, {set.view->id, set.view->carets[0], GetTimeSeconds()}); Add(&window->goto_history, {set.view->id, set.view->carets[0], GetTimeSeconds()});
GotoCrumb c = GetCrumb(&window->goto_redo); GotoCrumb c = PopCrumb(&window->goto_redo);
window->active_view = c.view_id; window->active_view = c.view_id;
View *view = GetView(c.view_id); View *view = GetView(c.view_id);
view->carets[0] = c.caret; view->carets[0] = c.caret;
@@ -281,7 +301,7 @@ void GotoForward(Window *window) {
if (window->goto_redo.len) { if (window->goto_redo.len) {
GotoCrumb *next = GetLast(window->goto_redo); GotoCrumb *next = GetLast(window->goto_redo);
if (c.view_id == next->view_id && next->time - c.time <= ConfigJumpHistoryMergeTimeWindow) { if (c.view_id == next->view_id && next->time - c.time <= ConfigJumpHistoryMergeTimeWindow) {
GotoForward(window); JumpForward(window);
} }
} }
} }

View File

@@ -36,7 +36,6 @@ struct Window {
uint32_t lose_focus_on_escape : 1; uint32_t lose_focus_on_escape : 1;
uint32_t lose_visibility_on_escape : 1; uint32_t lose_visibility_on_escape : 1;
uint32_t jump_history : 1; uint32_t jump_history : 1;
uint32_t eval_command : 1;
uint32_t skip_checkpoint : 1; uint32_t skip_checkpoint : 1;
}; };
}; };

View File

@@ -110,7 +110,7 @@ void CommandWindowUpdate() {
} }
void Command_ShowCommands() { void Command_ShowCommands() {
if (ActiveWindowID == CommandWindowID && LastExecutedCommand == Command_ShowCommands) { if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == Command_ShowCommands) {
NextActiveWindowID = LastActiveLayoutWindowID; NextActiveWindowID = LastActiveLayoutWindowID;
return; return;
} }
@@ -118,18 +118,20 @@ void Command_ShowCommands() {
BSet command_bar = GetBSet(CommandWindowID); BSet command_bar = GetBSet(CommandWindowID);
command_bar.window->visible = true; command_bar.window->visible = true;
command_bar.window->eval_command = true;
NextActiveWindowID = command_bar.window->id; NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer); ResetBuffer(command_bar.buffer);
For(CommandFunctions) { For (CommandFunctions) {
RawAppendf(command_bar.buffer, "\n%S", it.name); if (it.name == "OpenCommand") {
continue;
}
RawAppendf(command_bar.buffer, "\n:%S", it.name);
} }
command_bar.view->update_scroll = true; command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer)); SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowCommands, "ctrl-shift-p"); } RegisterCommand(Command_ShowCommands, "ctrl-shift-p");
void Command_ShowDebugBufferList() { void Command_ShowDebugBufferList() {
if (ActiveWindowID == CommandWindowID && LastExecutedCommand == Command_ShowDebugBufferList) { if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == Command_ShowDebugBufferList) {
NextActiveWindowID = LastActiveLayoutWindowID; NextActiveWindowID = LastActiveLayoutWindowID;
return; return;
} }
@@ -137,7 +139,6 @@ void Command_ShowDebugBufferList() {
BSet command_bar = GetBSet(CommandWindowID); BSet command_bar = GetBSet(CommandWindowID);
command_bar.window->visible = true; command_bar.window->visible = true;
command_bar.window->eval_command = false;
NextActiveWindowID = command_bar.window->id; NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer); ResetBuffer(command_bar.buffer);
For (Buffers) { For (Buffers) {
@@ -148,7 +149,7 @@ void Command_ShowDebugBufferList() {
} RegisterCommand(Command_ShowDebugBufferList, ""); } RegisterCommand(Command_ShowDebugBufferList, "");
void Command_ShowBufferList() { void Command_ShowBufferList() {
if (ActiveWindowID == CommandWindowID && LastExecutedCommand == Command_ShowBufferList) { if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == Command_ShowBufferList) {
NextActiveWindowID = LastActiveLayoutWindowID; NextActiveWindowID = LastActiveLayoutWindowID;
return; return;
} }
@@ -156,11 +157,10 @@ void Command_ShowBufferList() {
BSet command_bar = GetBSet(CommandWindowID); BSet command_bar = GetBSet(CommandWindowID);
command_bar.window->visible = true; command_bar.window->visible = true;
command_bar.window->eval_command = false;
NextActiveWindowID = command_bar.window->id; NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer); ResetBuffer(command_bar.buffer);
For (Buffers) { For (Buffers) {
if (it->special || it->garbage || it->is_dir) { if (it->special || it->garbage) {
continue; continue;
} }
RawAppendf(command_bar.buffer, "\n%S", it->name); RawAppendf(command_bar.buffer, "\n%S", it->name);
@@ -169,21 +169,6 @@ void Command_ShowBufferList() {
SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer)); SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowBufferList, "ctrl-p"); } RegisterCommand(Command_ShowBufferList, "ctrl-p");
void EvalCommand(String command) {
For (CommandFunctions) {
if (it.name == command) {
ProfileScopeEx(it.name);
it.function();
break;
}
}
}
void EvalCommand(String16 command) {
Scratch scratch;
EvalCommand(ToString(scratch, command));
}
void OpenCommand(BSet active) { void OpenCommand(BSet active) {
ProfileFunction(); ProfileFunction();
Range range = active.view->carets[0].range; Range range = active.view->carets[0].range;
@@ -193,20 +178,10 @@ void OpenCommand(BSet active) {
if (line == 0) { if (line == 0) {
line = ClampTop(1ll, active.buffer->line_starts.len - 1ll); line = ClampTop(1ll, active.buffer->line_starts.len - 1ll);
} }
string = GetLineStringWithoutNL(active.buffer, line); string = GetLineStringWithoutNL(active.buffer, line);
Int idx = 0;
if (Seek(string, u"||", &idx)) {
string = Skip(string, idx + 3);
}
}
if (active.window->eval_command) {
BSet main = GetBSet(LastActiveLayoutWindowID);
NextActiveWindowID = main.window->id;
EvalCommand(string);
} else {
Open(string);
} }
Open(string);
} }
void Command_OpenCommand() { void Command_OpenCommand() {
@@ -214,5 +189,7 @@ void Command_OpenCommand() {
return; return;
} }
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
BSet main = GetBSet(LastActiveLayoutWindowID);
NextActiveWindowID = main.window->id;
OpenCommand(active); OpenCommand(active);
} RegisterCommand(Command_OpenCommand, "ctrl-q | enter"); } RegisterCommand(Command_OpenCommand, "ctrl-q | enter");