diff --git a/src/backup/todo.txt b/src/backup/todo.txt index 155bed4..e46be26 100644 --- a/src/backup/todo.txt +++ b/src/backup/todo.txt @@ -37,7 +37,7 @@ Commands TODO: - Turned off by default - Special: non editable, hotkeys don't work etc. - +- RegisterCommand(Command_ShowCommands, KEY_P | KEY_CTRL) diff --git a/src/basic/basic_head.h b/src/basic/basic_head.h index 866e2ca..79b3246 100644 --- a/src/basic/basic_head.h +++ b/src/basic/basic_head.h @@ -212,4 +212,9 @@ inline uint64_t GetRandomU64(RandomSeed *state) { x ^= x >> 7; x ^= x << 17; return state->a = x; -} \ No newline at end of file +} + +#define STRINGIFY_(x) x +#define STRINGIFY(x) STRINGIFY_(x) +#define CONCAT_(a, b) a ## b +#define CONCAT(a, b) CONCAT_(a, b) diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 2f1ef6f..11ae934 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -654,15 +654,6 @@ void ConvertLineEndingsToLF(Buffer *buffer, bool trim_lines_with_caret = false) view->update_scroll = false; } -int Lua_ConvertLineEndingsToLF(lua_State *L) { - lua_Integer buffer_id = luaL_checkinteger(L, 1); - int trim_lines_with_caret = lua_toboolean(L, 2); - lua_pop(L, 2); - Buffer *buffer = GetBuffer({buffer_id}); - ConvertLineEndingsToLF(buffer, trim_lines_with_caret); - return 0; -} - void ApplyClangFormat(Buffer *buffer) { Scratch scratch; String string = AllocCharString(scratch, buffer); @@ -670,22 +661,6 @@ void ApplyClangFormat(Buffer *buffer) { ReplaceWithoutMovingCarets(buffer, GetRange(buffer), {temp_buffer->str, temp_buffer->len}); } -int Lua_ApplyClangFormat(lua_State *L) { - lua_Integer buffer_id = luaL_checkinteger(L, 1); - lua_pop(L, 1); - Buffer *buffer = GetBuffer({buffer_id}); - ApplyClangFormat(buffer); - return 0; -} - -int Lua_GetBufferNameByID(lua_State *L) { - lua_Integer buffer_id = luaL_checkinteger(L, 1); - lua_pop(L, 1); - Buffer *buffer = GetBuffer({buffer_id}); - lua_pushlstring(L, buffer->name.data, buffer->name.len); - return 1; -} - void SaveBuffer(Buffer *buffer) { CallOnSave(buffer->id); @@ -707,11 +682,6 @@ void Command_Save() { SaveBuffer(active.buffer); } RegisterCommand(Command_Save); -int Lua_Save(lua_State *L) { - Command_Save(); - return 0; -} - void Command_SaveAll() { For(Buffers) { if (it->file_mod_time) { @@ -720,11 +690,6 @@ void Command_SaveAll() { } } RegisterCommand(Command_SaveAll); -int Lua_SaveAll(lua_State *L) { - Command_SaveAll(); - return 0; -} - void KillSelectedLines(View *view) { Scratch scratch; Buffer *buffer = GetBuffer(view->active_buffer); @@ -994,11 +959,6 @@ void Command_Reopen() { NextActiveWindowID = main.window->id; } RegisterCommand(Command_Reopen); -int Lua_Reopen(lua_State *L) { - Command_Reopen(); - return 0; -} - void New(Window *window, String name = "") { View *view = GetView(window->active_view); Buffer *buffer = GetBuffer(view->active_buffer); @@ -1021,14 +981,6 @@ void Command_New() { New(main.window, ""); } RegisterCommand(Command_New); -int Lua_New(lua_State *L) { - String name = lua_tostring(L, 1); - lua_pop(L, 1); - BSet main = GetBSet(LastActiveLayoutWindowID); - New(main.window, name); - return 0; -} - void NewDir(Window *window, String name = "") { View *view = GetView(window->active_view); Buffer *buffer = GetBuffer(view->active_buffer); @@ -1048,14 +1000,6 @@ void NewDir(Window *window, String name = "") { Open(name); } -int Lua_NewDir(lua_State *L) { - String name = lua_tostring(L, 1); - lua_pop(L, 1); - BSet main = GetBSet(LastActiveLayoutWindowID); - NewDir(main.window, name); - return 0; -} - void Command_ToggleFullscreen() { if (IsInFullscreen) { SDL_SetWindowSize(SDLWindow, FullScreenSizeX, FullScreenSizeY); @@ -1073,11 +1017,6 @@ void Command_ToggleFullscreen() { IsInFullscreen = !IsInFullscreen; } RegisterCommand(Command_ToggleFullscreen); -int Lua_ToggleFullscreen(lua_State *L) { - Command_ToggleFullscreen(); - return 0; -} - void ListFilesRecursive(Buffer *buffer, String dir) { Scratch scratch(buffer->line_starts.allocator); for (FileIter it = IterateFiles(scratch, dir); IsValid(it); Advance(&it)) { @@ -1105,11 +1044,6 @@ void Command_ListCode() { SelectRange(main.view, GetBufferEndAsRange(main.buffer)); } RegisterCommand(Command_ListCode); -int Lua_ListCode(lua_State *L) { - Command_ListCode(); - return 0; -} - View *ExecHidden(String buffer_name, String cmd, String working_dir) { View *view = OpenBufferView(buffer_name); Exec(view->id, true, cmd, working_dir); @@ -1126,13 +1060,6 @@ BSet Exec(String cmd, String working_dir, bool set_active = true) { return main; } -int Lua_C(lua_State *L) { - String string = lua_tostring(L, 1); - lua_pop(L, 1); - Exec(string, GetMainDir()); - return 0; -} - BSet Open(Window *window, String path, String meta, bool set_active = true) { Scratch scratch; BSet set = GetBSet(window); @@ -1190,62 +1117,10 @@ BSet Open(String16 path, String meta) { return Open(string, meta); } -int Lua_Open(lua_State *L) { - Scratch scratch; - String path = luaL_checkstring(L, 1); - lua_pop(L, 1); - Open(path); - return 0; -} - -int Lua_Cmd(lua_State *L) { - if (!lua_istable(L, -1)) luaL_error(L, "expected a table as argument"); - defer { lua_pop(L, 1); }; - - lua_getfield(L, -1, "working_dir"); - String working_dir = lua_tostring(L, -1); - lua_pop(L, 1); - if (working_dir == "") { - working_dir = GetMainDir(); - } - - lua_getfield(L, -1, "cmd"); - if (!lua_isstring(L, -1)) luaL_error(L, "expected a string for cmd param"); - String cmd = lua_tostring(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "kind"); - String kind = lua_tostring(L, -1); - lua_pop(L, 1); - - BSet main = GetBSet(LastActiveLayoutWindowID); - if (kind == "console") { - BSet set = GetConsoleSet(); - main.window->active_goto_list = set.view->id; - main.window->goto_list_pos = set.buffer->len; - SelectRange(set.view, MakeRange(set.buffer->len)); - BeginJump(&set); - Exec(set.view->id, true, cmd, working_dir); - EndJump(set); - } else if (kind == "fuzzy") { - JumpGarbageBuffer(&main); - Exec(main.view->id, true, cmd, working_dir); - main.view->fuzzy_search = true; - NextActiveWindowID = main.window->id; - } else { - JumpGarbageBuffer(&main); - main.window->active_goto_list = main.view->id; - main.window->goto_list_pos = 0; - Exec(main.view->id, true, cmd, working_dir); - NextActiveWindowID = main.window->id; - } - - return 0; -} - void Command_ShowBufferList() { BSet command_bar = GetBSet(CommandBarWindowID); command_bar.window->visible = true; + command_bar.window->eval_command = false; NextActiveWindowID = command_bar.window->id; ResetBuffer(command_bar.buffer); For(Buffers) { @@ -1258,12 +1133,12 @@ void Command_ShowBufferList() { void Command_ShowCommandList() { BSet command_bar = GetBSet(CommandBarWindowID); command_bar.window->visible = true; + command_bar.window->eval_command = false; NextActiveWindowID = command_bar.window->id; ResetBuffer(command_bar.buffer); - for (int i = 0; LuaFunctions[i].name != NULL; i += 1) { - Appendf(command_bar.view, "%s()\n ", LuaFunctions[i].name); + For(LuaFunctions) { + Appendf(command_bar.view, "%S()\n ", it.name); } - command_bar.view->update_scroll = true; SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer)); } RegisterCommand(Command_ShowCommandList); @@ -1271,6 +1146,7 @@ void Command_ShowCommandList() { void Command_ListViews() { BSet command_bar = GetBSet(CommandBarWindowID); command_bar.window->visible = true; + command_bar.window->eval_command = false; NextActiveWindowID = command_bar.window->id; ResetBuffer(command_bar.buffer); For(Views) { @@ -1282,11 +1158,6 @@ void Command_ListViews() { SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer)); } RegisterCommand(Command_ListViews); -int Lua_ListViews(lua_State *L) { - Command_ListViews(); - return 0; -} - void Eval(String string) { if (luaL_dostring(LuaState, string.data) != LUA_OK) { const char *error_message = lua_tostring(LuaState, -1); @@ -1300,14 +1171,6 @@ void Eval(String16 string) { Eval(ToString(scratch, string)); } -int Lua_Eval(lua_State *L) { - String string = lua_tostring(L, 1); - lua_pop(L, 1); - Eval(string); - - return 0; -} - void SetProjectFile(Buffer *buffer) { WorkDir = ChopLastSlash(buffer->name); LuaProjectBuffer = buffer; @@ -1334,80 +1197,6 @@ void Command_SetProject() { Command_SetProjectFile(); } RegisterCommand(Command_SetProject); -int Lua_SetProjectFile(lua_State *L) { - Command_SetProjectFile(); - return 0; -} - -int Lua_SetWorkDir(lua_State *L) { - Command_SetWorkDir(); - return 0; -} - -int Lua_ListCommands(lua_State *L) { - BSet main = GetBSet(LastActiveLayoutWindowID); - BeginJump(&main); - for (int i = 0; LuaFunctions[i].name != NULL; i += 1) { - Appendf(main.view, "%20s() ", LuaFunctions[i].name); - if (((i + 1) % 6) == 0) { - Appendf(main.view, "\n"); - } - } - EndJump(main); - NextActiveWindowID = main.window->id; - return 0; -} - -int Lua_GetBufferList(lua_State *L) { - lua_createtable(L, 0, (int)Buffers.len); - - int i = 1; - For(Buffers) { - lua_pushinteger(L, i++); - lua_pushlstring(L, it->name.data, it->name.len); - lua_settable(L, -3); /* 3rd element from the stack top */ - } - /* We still have table left on top of the Lua stack. */ - return 1; -} - -Window *GetOverlappingWindow(Vec2I p, Window *default_window = NULL) { - For(Windows) { - if (AreOverlapping(p, it->total_rect)) { - return it; - } - } - return default_window; -} - -Vec2I GetSideOfWindow(Window *window, int direction) { - Vec2I p = {}; - Rect2I rect = window->total_rect; - float resizer_size = (float)window->font->char_spacing*0.5f; // @check_codebase_when_changing - if (direction == DIR_LEFT) { - p.x = rect.min.x - (Int)(resizer_size + window->font->char_spacing); - p.y = rect.min.y + (rect.max.y / 2); - } else if (direction == DIR_RIGHT) { - p.x = rect.max.x + (Int)(resizer_size + window->font->char_spacing); - p.y = rect.min.y + (rect.max.y / 2); - } else if (direction == DIR_UP) { - p.x = rect.min.x + (rect.max.x / 2); - p.y = rect.min.y - (Int)(resizer_size + window->font->line_spacing); - } else { - Assert(direction == DIR_DOWN); - p.x = rect.min.x + (rect.max.x / 2); - p.y = rect.max.y + (Int)(resizer_size + window->font->line_spacing); - } - return p; -} - -Window *SwitchWindow(int direction) { - Window *window = GetWindow(ActiveWindowID); - Vec2I p = GetSideOfWindow(window, direction); - Window *result = GetOverlappingWindow(p, window); - return result; -} - String16 FetchLoadWord(void) { BSet active = GetBSet(ActiveWindowID); Caret caret = active.view->carets[0]; @@ -1427,17 +1216,20 @@ void Command_KillProcess() { KillProcess(main.view); } RegisterCommand(Command_KillProcess); -int Lua_KillProcess(lua_State *L) { - Command_KillProcess(); - return 0; -} - void Command_KillWindow() { BSet main = GetBSet(LastActiveLayoutWindowID); main.window->kill = true; } RegisterCommand(Command_KillWindow); -int Lua_KillWindow(lua_State *L) { - Command_KillWindow(); - return 0; -} +void Command_ShowCommands() { + BSet command_bar = GetBSet(CommandBarWindowID); + command_bar.window->visible = true; + command_bar.window->eval_command = true; + NextActiveWindowID = command_bar.window->id; + ResetBuffer(command_bar.buffer); + For(CommandFunctions) { + Appendf(command_bar.view, "%S\n", it.name); + } + command_bar.view->update_scroll = true; + SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer)); +} RegisterCommand(Command_ShowCommands); \ No newline at end of file diff --git a/src/text_editor/commands_bindings.cpp b/src/text_editor/commands_bindings.cpp index 29d5af3..e0255ec 100644 --- a/src/text_editor/commands_bindings.cpp +++ b/src/text_editor/commands_bindings.cpp @@ -46,26 +46,42 @@ void UpdateScroll(Window *window, bool update_caret_scrolling) { } } +void EvalCommand(String command) { + For (CommandFunctions) { + if (it.name == command) { + it.function(); + break; + } + } +} + +void EvalCommand(String16 command) { + Scratch scratch; + EvalCommand(ToString(scratch, command)); +} + void FuzzySearchOpen(BSet active) { - bool success = false; Range range = active.view->carets[0].range; + String16 string = FetchLoadWord(); if (GetSize(range) == 0) { Int line = PosToLine(active.buffer, range.min); if ((active.buffer->line_starts.len - 1) == line) { line = ClampBottom(0ll, line - 1ll); } - String16 string = GetLineStringWithoutNL(active.buffer, line); + string = GetLineStringWithoutNL(active.buffer, line); Int idx = 0; if (Seek(string, u"||", &idx)) { string = Skip(string, idx + 3); - Open(string); - success = true; } } - - if (!success) { - Open(FetchLoadWord()); + if (active.window->eval_command) { + BSet main = GetBSet(LastActiveLayoutWindowID); + NextActiveWindowID = main.window->id; + ActiveWindowID = main.window->id; + EvalCommand(string); + } else { + Open(string); } } @@ -304,7 +320,7 @@ void OnCommand(Event event) { if (CtrlAltPress(SDLK_P)) { } else if (CtrlShiftPress(SDLK_P)) { - Command_ShowCommandList(); + Command_ShowCommands(); } else if (CtrlPress(SDLK_P)) { Command_ShowBufferList(); } @@ -551,8 +567,8 @@ void OnCommand(Event event) { if (active.view->fuzzy_search) { if (!ProcessIsActive(active.view->id)) { - Scratch scratch; - String16 last_line_string = GetLineStringWithoutNL(active.buffer, active.buffer->line_starts.len - 1); + Scratch scratch; + String16 last_line_string = GetLineStringWithoutNL(active.buffer, active.buffer->line_starts.len - 1); if (active.view->prev_search_line != last_line_string) { active.view->prev_search_line = last_line_string; Array ratings = FuzzySearchLines(scratch, active.buffer, 0, active.buffer->line_starts.len - 1, last_line_string); diff --git a/src/text_editor/event.cpp b/src/text_editor/event.cpp index 6c0f4a8..70410b3 100644 --- a/src/text_editor/event.cpp +++ b/src/text_editor/event.cpp @@ -468,14 +468,6 @@ void Serialize(Serializer *s, Event *e) { SerializeEnd(s); } -const int DIR_RIGHT = 0; -const int DIR_LEFT = 1; -const int DIR_DOWN = 2; -const int DIR_UP = 3; -const int DIR_COUNT = 4; -const bool CTRL_PRESSED = true; -const bool SHIFT_PRESS = true; - #define Ctrl() event.ctrl #define Alt() event.alt #define Shift() event.shift diff --git a/src/text_editor/globals.cpp b/src/text_editor/globals.cpp index 5f1af01..7e93eaf 100644 --- a/src/text_editor/globals.cpp +++ b/src/text_editor/globals.cpp @@ -50,11 +50,7 @@ View *TraceView; String WorkDir; RandomSeed UniqueBufferNameSeed = {}; Array EventPlayback; - -// lua -lua_State *LuaState = NULL; -String16 LuaCommandResult = {}; -extern luaL_Reg LuaFunctions[]; +lua_State *LuaState = NULL; // clipboard BlockArena ClipboardArena; @@ -187,16 +183,24 @@ void ReloadStyle() { } typedef void CommandFunction(void); -Array CommandFunctions; - -#define STRINGIFY_(x) x -#define STRINGIFY(x) STRINGIFY_(x) -#define CONCAT_(a, b) a ## b -#define CONCAT(a, b) CONCAT_(a, b) - -struct Register_Command { - Register_Command(CommandFunction *f) { - Add(&CommandFunctions, f); - } +struct CommandFunctionMeta { + String name; + CommandFunction *function; }; -#define RegisterCommand(NAME) Register_Command CONCAT(COMMAND, __COUNTER__)(NAME) \ No newline at end of file +Array CommandFunctions; +struct Register_Command { Register_Command(String name, CommandFunction *f) { if (StartsWith(name, "Command_")) name = Skip(name, 8);Add(&CommandFunctions, {name, f}); } }; +#define RegisterCommand(NAME) Register_Command CONCAT(COMMAND, __COUNTER__)(#NAME, NAME) + +typedef int LuaFunction(lua_State *state); +struct LuaFunctionMeta { String name; LuaFunction *function; }; +Array LuaFunctions; +struct Register_Lua { Register_Lua(LuaFunction *function, String name) { if (StartsWith(name, "Lua_")) name = Skip(name, 4); Add(&LuaFunctions, {name, function}); } }; +#define RegisterLua(NAME) Register_Lua CONCAT(COMMAND, __COUNTER__)(NAME, #NAME) + +const int DIR_RIGHT = 0; +const int DIR_LEFT = 1; +const int DIR_DOWN = 2; +const int DIR_UP = 3; +const int DIR_COUNT = 4; +const bool CTRL_PRESSED = true; +const bool SHIFT_PRESS = true; \ No newline at end of file diff --git a/src/text_editor/lua.cpp b/src/text_editor/lua.cpp index 2819bc3..8b95f1d 100644 --- a/src/text_editor/lua.cpp +++ b/src/text_editor/lua.cpp @@ -86,61 +86,6 @@ API String GetFieldString(lua_State *L, String name) { return result; } -Int GetFieldAInt(lua_State *L, const char *name) { - lua_getfield(L, -1, name); - lua_Integer num = lua_tointeger(L, -1); - lua_pop(L, 1); - return (Int)num; -} - -double GetFieldAFloat(lua_State *L, const char *name) { - lua_getfield(L, -1, name); - double num = lua_tonumber(L, -1); - lua_pop(L, 1); - return num; -} - -const char *GetFieldAString(lua_State *L, const char *name) { - lua_getfield(L, -1, name); - const char *result = lua_tostring(L, -1); - - lua_pop(L, 1); - return result; -} - -API void PushEvent(lua_State *L, Event *event) { - lua_createtable(L, 0, EVENT_FIELD_COUNT); -#define lua_pushInt lua_pushinteger -#define lua_pushString lua_pushstring -#define lua_pushFloat lua_pushnumber -#define X(TYPE, KIND, NAME) \ - lua_push##KIND(L, event->NAME); \ - lua_setfield(L, -2, #NAME); - EVENT_FIELDS -#undef X -} - -// :Event -API int Lua_Play(lua_State *L) { - if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); - defer { lua_pop(L, 1); }; - - int size = (int)lua_rawlen(L, -1); - for (int i = 0; i < size; i += 1) { - lua_geti(L, -1, i + 1); - if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); - defer { lua_pop(L, 1); }; - - Event event = {}; -#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetFieldA##KIND(L, #NAME); - EVENT_FIELDS -#undef X - Add(&EventPlayback, event); - } - - return 0; -} - void ReloadStyle(); extern String BaseLuaConfig; @@ -206,9 +151,9 @@ API void InitLuaConfig() { luaL_openlibs(LuaState); lua_sethook(LuaState, HookLuaForceExit, LUA_MASKCOUNT, 100000000); - for (int i = 0; LuaFunctions[i].name; i += 1) { - lua_pushcfunction(LuaState, LuaFunctions[i].func); - lua_setglobal(LuaState, LuaFunctions[i].name); + For(LuaFunctions) { + lua_pushcfunction(LuaState, it.function); + lua_setglobal(LuaState, it.name.data); } #if OS_WINDOWS @@ -253,3 +198,97 @@ API void InitLuaConfig() { ReloadLuaConfigs(true); CallLuaOnInit(); } + +struct OnOpenResult { + String kind; + String file_path; + Int line, col; + String working_dir; + String cmd; +}; + +OnOpenResult CallOnOpen(Allocator allocator, String path, String meta) { + lua_getglobal(LuaState, "OnOpen"); + lua_pushlstring(LuaState, path.data, path.len); + lua_pushlstring(LuaState, meta.data, meta.len); + if (!CallLuaFunc("OnOpen", 2, 1)) { + return {}; + } + + String file_path = GetFieldString(LuaState, "file_path"); + String line_string = GetFieldString(LuaState, "line"); + String col_string = GetFieldString(LuaState, "col"); + String cmd = GetFieldString(LuaState, "cmd"); + String working_dir = GetFieldString(LuaState, "working_dir"); + String kind = GetFieldString(LuaState, "kind"); + + OnOpenResult result = {}; + result.cmd = cmd; + result.working_dir = working_dir; + result.file_path = file_path; + if (!IsAbsolute(result.file_path)) { + String GetMainDir(); + String dir = GetMainDir(); + result.file_path = Format(allocator, "%S/%S", dir, result.file_path); + } + if (col_string.len) { + result.col = strtoll(col_string.data, NULL, 10); + } else { + result.col = -1; + } + if (line_string.len) { + result.line = strtoll(line_string.data, NULL, 10); + } else { + result.line = -1; + } + result.kind = kind; + + + return result; +} + +bool CallIsCode(String path, String meta = "") { + lua_getglobal(LuaState, "IsCode"); + lua_pushlstring(LuaState, path.data, path.len); + lua_pushlstring(LuaState, meta.data, meta.len); + if (!CallLuaFunc("IsCode", 2, 1)) { + return false; + } + + bool result = lua_toboolean(LuaState, -1); + lua_pop(LuaState, 1); + return result; +} + +void CallOnSave(BufferID buffer_id) { + lua_getglobal(LuaState, "OnSave"); + lua_pushinteger(LuaState, buffer_id.id); + CallLuaFunc("OnSave", 1, 0); +} + +void PushEvent(lua_State *L, Event *event) { + lua_createtable(L, 0, EVENT_FIELD_COUNT); +#define lua_pushInt lua_pushinteger +#define lua_pushString lua_pushstring +#define lua_pushFloat lua_pushnumber +#define X(TYPE, KIND, NAME) \ + lua_push##KIND(L, event->NAME); \ + lua_setfield(L, -2, #NAME); + EVENT_FIELDS +#undef X +} + +bool CallOnCommand(Event *event) { + lua_getglobal(LuaState, "OnCommand"); + PushEvent(LuaState, event); + CallLuaFunc("OnCommand", 1, 1); + bool result = lua_toboolean(LuaState, -1); + lua_pop(LuaState, 1); + return result; +} + +void CallLuaOnUpdate(Event *event) { + lua_getglobal(LuaState, "OnUpdate"); + PushEvent(LuaState, event); + CallLuaFunc("OnUpdate", 1, 0); +} diff --git a/src/text_editor/lua.h b/src/text_editor/lua.h index b712f0b..d7aefa4 100644 --- a/src/text_editor/lua.h +++ b/src/text_editor/lua.h @@ -3,7 +3,6 @@ API Int GetStyleInt(String name, Int default_int); API String GetStyleString(String name, String default_string); API Color GetColor(String name, Color default_color); API String GetFieldString(lua_State *L, String name); -API int Lua_Play(lua_State *L); API void LoadLuaBuffer(Buffer *lua_buffer); API void ReloadLuaConfigs(bool reload = false); API bool CallLuaFunc(char *func_name, int arg_count, int ret_count); diff --git a/src/text_editor/lua_api.cpp b/src/text_editor/lua_api.cpp index f8a0512..d39e439 100644 --- a/src/text_editor/lua_api.cpp +++ b/src/text_editor/lua_api.cpp @@ -9,7 +9,7 @@ int Lua_print(lua_State *L) { Appendf(null_view, "\n"); lua_pop(L, nargs); return 0; -} +} RegisterLua(Lua_print); int Lua_Print(lua_State *L) { Scratch scratch; @@ -21,7 +21,7 @@ int Lua_Print(lua_State *L) { Appendf(TraceView, "\n"); lua_pop(L, nargs); return 0; -} +} RegisterLua(Lua_Print); int Lua_GetLoadWord(lua_State *L) { BSet active = GetBSet(ActiveWindowID); @@ -34,7 +34,7 @@ int Lua_GetLoadWord(lua_State *L) { String string = AllocCharString(scratch, active.buffer, range); lua_pushlstring(L, string.data, string.len); return 1; -} +} RegisterLua(Lua_GetLoadWord); int Lua_BufferExists(lua_State *L) { String string = lua_tostring(L, 1); @@ -42,7 +42,7 @@ int Lua_BufferExists(lua_State *L) { Buffer *buffer = GetBuffer(string); lua_pushboolean(L, buffer != NULL); return 1; -} +} RegisterLua(Lua_BufferExists); int Lua_GetSelection(lua_State *L) { Scratch scratch; @@ -51,7 +51,7 @@ int Lua_GetSelection(lua_State *L) { String string = ToString(scratch, string16); lua_pushlstring(L, string.data, string.len); return 1; -} +} RegisterLua(Lua_GetSelection); int Lua_GetEntireBuffer(lua_State *L) { Scratch scratch; @@ -60,20 +60,20 @@ int Lua_GetEntireBuffer(lua_State *L) { String string = ToString(scratch, string16); lua_pushlstring(L, string.data, string.len); return 1; -} +} RegisterLua(Lua_GetEntireBuffer); int Lua_GetClipboard(lua_State *L) { Scratch scratch; String string = ToString(scratch, SavedClipboardString); lua_pushlstring(L, string.data, string.len); return 1; -} +} RegisterLua(Lua_GetClipboard); int Lua_GetFilename(lua_State *L) { BSet main = GetBSet(LastActiveLayoutWindowID); lua_pushlstring(L, main.buffer->name.data, main.buffer->name.len); return 1; -} +} RegisterLua(Lua_GetFilename); int Lua_GetLine(lua_State *L) { BSet main = GetBSet(LastActiveLayoutWindowID); @@ -82,7 +82,7 @@ int Lua_GetLine(lua_State *L) { Int line = PosToLine(main.buffer, front); lua_pushinteger(L, line + 1); return 1; -} +} RegisterLua(Lua_GetLine); int Lua_FileExists(lua_State *L) { String path = luaL_checkstring(L, 1); @@ -90,103 +90,254 @@ int Lua_FileExists(lua_State *L) { bool exists = FileExists(path); lua_pushboolean(L, exists); return 1; -} +} RegisterLua(Lua_FileExists); int Lua_GetWorkDir(lua_State *L) { lua_pushlstring(L, WorkDir.data, WorkDir.len); return 1; -} +} RegisterLua(Lua_GetWorkDir); int Lua_GetExeDir(lua_State *L) { Scratch scratch; String exe_dir = GetExeDir(scratch); lua_pushlstring(L, exe_dir.data, exe_dir.len); return 1; -} +} RegisterLua(Lua_GetExeDir); int Lua_GetMainDir(lua_State *L) { String name = GetMainDir(); lua_pushlstring(L, name.data, name.len); return 1; -} +} RegisterLua(Lua_GetMainDir); -struct OnOpenResult { - String kind; - String file_path; - Int line, col; - String working_dir; - String cmd; -}; +int Lua_KillProcess(lua_State *L) { + Command_KillProcess(); + return 0; +} RegisterLua(Lua_KillProcess); -OnOpenResult CallOnOpen(Allocator allocator, String path, String meta) { - lua_getglobal(LuaState, "OnOpen"); - lua_pushlstring(LuaState, path.data, path.len); - lua_pushlstring(LuaState, meta.data, meta.len); - if (!CallLuaFunc("OnOpen", 2, 1)) { - return {}; +int Lua_KillWindow(lua_State *L) { + Command_KillWindow(); + return 0; +} RegisterLua(Lua_KillWindow); + +int Lua_SetProjectFile(lua_State *L) { + Command_SetProjectFile(); + return 0; +} RegisterLua(Lua_SetProjectFile); + +int Lua_SetWorkDir(lua_State *L) { + Command_SetWorkDir(); + return 0; +} RegisterLua(Lua_SetWorkDir); + +int Lua_ListCommands(lua_State *L) { + BSet main = GetBSet(LastActiveLayoutWindowID); + BeginJump(&main); + int i = 0; + For (LuaFunctions) { + Appendf(main.view, "%20S() ", it.name); + if (((i + 1) % 6) == 0) { + Appendf(main.view, "\n"); + } + i += 1; + } + EndJump(main); + NextActiveWindowID = main.window->id; + return 0; +} RegisterLua(Lua_ListCommands); + +int Lua_GetBufferList(lua_State *L) { + lua_createtable(L, 0, (int)Buffers.len); + + int i = 1; + For(Buffers) { + lua_pushinteger(L, i++); + lua_pushlstring(L, it->name.data, it->name.len); + lua_settable(L, -3); /* 3rd element from the stack top */ + } + /* We still have table left on top of the Lua stack. */ + return 1; +} RegisterLua(Lua_GetBufferList); + +int Lua_Eval(lua_State *L) { + String string = lua_tostring(L, 1); + lua_pop(L, 1); + Eval(string); + return 0; +} RegisterLua(Lua_Eval); + +int Lua_ListViews(lua_State *L) { + Command_ListViews(); + return 0; +} RegisterLua(Lua_ListViews); + +int Lua_ApplyClangFormat(lua_State *L) { + lua_Integer buffer_id = luaL_checkinteger(L, 1); + lua_pop(L, 1); + Buffer *buffer = GetBuffer({buffer_id}); + ApplyClangFormat(buffer); + return 0; +} RegisterLua(Lua_ApplyClangFormat); + +int Lua_GetBufferNameByID(lua_State *L) { + lua_Integer buffer_id = luaL_checkinteger(L, 1); + lua_pop(L, 1); + Buffer *buffer = GetBuffer({buffer_id}); + lua_pushlstring(L, buffer->name.data, buffer->name.len); + return 1; +} RegisterLua(Lua_GetBufferNameByID); + + +int Lua_ConvertLineEndingsToLF(lua_State *L) { + lua_Integer buffer_id = luaL_checkinteger(L, 1); + int trim_lines_with_caret = lua_toboolean(L, 2); + lua_pop(L, 2); + Buffer *buffer = GetBuffer({buffer_id}); + ConvertLineEndingsToLF(buffer, trim_lines_with_caret); + return 0; +} RegisterLua(Lua_ConvertLineEndingsToLF); + +int Lua_Save(lua_State *L) { + Command_Save(); + return 0; +} RegisterLua(Lua_Save); + +int Lua_SaveAll(lua_State *L) { + Command_SaveAll(); + return 0; +} RegisterLua(Lua_SaveAll); + +int Lua_Reopen(lua_State *L) { + Command_Reopen(); + return 0; +} RegisterLua(Lua_Reopen); + +int Lua_New(lua_State *L) { + String name = lua_tostring(L, 1); + lua_pop(L, 1); + BSet main = GetBSet(LastActiveLayoutWindowID); + New(main.window, name); + return 0; +} RegisterLua(Lua_New); + +int Lua_NewDir(lua_State *L) { + String name = lua_tostring(L, 1); + lua_pop(L, 1); + BSet main = GetBSet(LastActiveLayoutWindowID); + NewDir(main.window, name); + return 0; +} RegisterLua(Lua_NewDir); + +int Lua_ToggleFullscreen(lua_State *L) { + Command_ToggleFullscreen(); + return 0; +} RegisterLua(Lua_ToggleFullscreen); + +int Lua_ListCode(lua_State *L) { + Command_ListCode(); + return 0; +} RegisterLua(Lua_ListCode); + +int Lua_C(lua_State *L) { + String string = lua_tostring(L, 1); + lua_pop(L, 1); + Exec(string, GetMainDir()); + return 0; +} RegisterLua(Lua_C); + +int Lua_Open(lua_State *L) { + Scratch scratch; + String path = luaL_checkstring(L, 1); + lua_pop(L, 1); + Open(path); + return 0; +} RegisterLua(Lua_Open); + +int Lua_Cmd(lua_State *L) { + if (!lua_istable(L, -1)) luaL_error(L, "expected a table as argument"); + defer { lua_pop(L, 1); }; + + lua_getfield(L, -1, "working_dir"); + String working_dir = lua_tostring(L, -1); + lua_pop(L, 1); + if (working_dir == "") { + working_dir = GetMainDir(); } - String file_path = GetFieldString(LuaState, "file_path"); - String line_string = GetFieldString(LuaState, "line"); - String col_string = GetFieldString(LuaState, "col"); - String cmd = GetFieldString(LuaState, "cmd"); - String working_dir = GetFieldString(LuaState, "working_dir"); - String kind = GetFieldString(LuaState, "kind"); + lua_getfield(L, -1, "cmd"); + if (!lua_isstring(L, -1)) luaL_error(L, "expected a string for cmd param"); + String cmd = lua_tostring(L, -1); + lua_pop(L, 1); - OnOpenResult result = {}; - result.cmd = cmd; - result.working_dir = working_dir; - result.file_path = file_path; - if (!IsAbsolute(result.file_path)) { - String dir = GetMainDir(); - result.file_path = Format(allocator, "%S/%S", dir, result.file_path); - } - if (col_string.len) { - result.col = strtoll(col_string.data, NULL, 10); + lua_getfield(L, -1, "kind"); + String kind = lua_tostring(L, -1); + lua_pop(L, 1); + + BSet main = GetBSet(LastActiveLayoutWindowID); + if (kind == "console") { + BSet set = GetConsoleSet(); + main.window->active_goto_list = set.view->id; + main.window->goto_list_pos = set.buffer->len; + SelectRange(set.view, MakeRange(set.buffer->len)); + BeginJump(&set); + Exec(set.view->id, true, cmd, working_dir); + EndJump(set); + } else if (kind == "fuzzy") { + JumpGarbageBuffer(&main); + Exec(main.view->id, true, cmd, working_dir); + main.view->fuzzy_search = true; + NextActiveWindowID = main.window->id; } else { - result.col = -1; + JumpGarbageBuffer(&main); + main.window->active_goto_list = main.view->id; + main.window->goto_list_pos = 0; + Exec(main.view->id, true, cmd, working_dir); + NextActiveWindowID = main.window->id; } - if (line_string.len) { - result.line = strtoll(line_string.data, NULL, 10); - } else { - result.line = -1; - } - result.kind = kind; + return 0; +} RegisterLua(Lua_Cmd); +Int GetFieldAInt(lua_State *L, const char *name) { + lua_getfield(L, -1, name); + lua_Integer num = lua_tointeger(L, -1); + lua_pop(L, 1); + return (Int)num; +} + +double GetFieldAFloat(lua_State *L, const char *name) { + lua_getfield(L, -1, name); + double num = lua_tonumber(L, -1); + lua_pop(L, 1); + return num; +} + +const char *GetFieldAString(lua_State *L, const char *name) { + lua_getfield(L, -1, name); + const char *result = lua_tostring(L, -1); + + lua_pop(L, 1); return result; } -bool CallIsCode(String path, String meta = "") { - lua_getglobal(LuaState, "IsCode"); - lua_pushlstring(LuaState, path.data, path.len); - lua_pushlstring(LuaState, meta.data, meta.len); - if (!CallLuaFunc("IsCode", 2, 1)) { - return false; +// :Event +int Lua_Play(lua_State *L) { + if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); + defer { lua_pop(L, 1); }; + + int size = (int)lua_rawlen(L, -1); + for (int i = 0; i < size; i += 1) { + lua_geti(L, -1, i + 1); + if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); + defer { lua_pop(L, 1); }; + + Event event = {}; +#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetFieldA##KIND(L, #NAME); + EVENT_FIELDS +#undef X + Add(&EventPlayback, event); } - bool result = lua_toboolean(LuaState, -1); - lua_pop(LuaState, 1); - return result; -} + return 0; +} RegisterLua(Lua_Play); -void CallOnSave(BufferID buffer_id) { - lua_getglobal(LuaState, "OnSave"); - lua_pushinteger(LuaState, buffer_id.id); - CallLuaFunc("OnSave", 1, 0); -} - -bool CallOnCommand(Event *event) { - lua_getglobal(LuaState, "OnCommand"); - PushEvent(LuaState, event); - CallLuaFunc("OnCommand", 1, 1); - bool result = lua_toboolean(LuaState, -1); - lua_pop(LuaState, 1); - return result; -} - -void CallLuaOnUpdate(Event *event) { - lua_getglobal(LuaState, "OnUpdate"); - PushEvent(LuaState, event); - CallLuaFunc("OnUpdate", 1, 0); -} diff --git a/src/text_editor/lua_api_generated.cpp b/src/text_editor/lua_api_generated.cpp deleted file mode 100644 index 22cf4b8..0000000 --- a/src/text_editor/lua_api_generated.cpp +++ /dev/null @@ -1,39 +0,0 @@ -luaL_Reg LuaFunctions[] = { - {"print", Lua_print}, - {"Print", Lua_Print}, - {"SaveAll", Lua_SaveAll}, - {"KillProcess", Lua_KillProcess}, - {"GetLoadWord", Lua_GetLoadWord}, - {"BufferExists", Lua_BufferExists}, - {"GetSelection", Lua_GetSelection}, - {"GetEntireBuffer", Lua_GetEntireBuffer}, - {"GetClipboard", Lua_GetClipboard}, - {"GetFilename", Lua_GetFilename}, - {"GetLine", Lua_GetLine}, - {"FileExists", Lua_FileExists}, - {"GetWorkDir", Lua_GetWorkDir}, - {"GetExeDir", Lua_GetExeDir}, - {"GetMainDir", Lua_GetMainDir}, - {"KillWindow", Lua_KillWindow}, - {"Play", Lua_Play}, - {"TrimTrailingWhitespace", Lua_TrimTrailingWhitespace}, - {"ConvertLineEndingsToLF", Lua_ConvertLineEndingsToLF}, - {"ApplyClangFormat", Lua_ApplyClangFormat}, - {"GetBufferNameByID", Lua_GetBufferNameByID}, - {"Save", Lua_Save}, - {"Reopen", Lua_Reopen}, - {"New", Lua_New}, - {"NewDir", Lua_NewDir}, - {"ToggleFullscreen", Lua_ToggleFullscreen}, - {"ListCode", Lua_ListCode}, - {"C", Lua_C}, - {"Open", Lua_Open}, - {"Cmd", Lua_Cmd}, - {"ListViews", Lua_ListViews}, - {"Eval", Lua_Eval}, - {"SetProjectFile", Lua_SetProjectFile}, - {"SetWorkDir", Lua_SetWorkDir}, - {"ListCommands", Lua_ListCommands}, - {"GetBufferList", Lua_GetBufferList}, - {NULL, NULL}, -}; diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 5a3e1ea..2869e06 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -34,13 +34,12 @@ #include "process.cpp" #include "event.cpp" -#include "lua_api.cpp" #include "commands.cpp" +#include "lua_api.cpp" #include "commands_clipboard.cpp" #include "commands_bindings.cpp" #include "title_bar.cpp" -#include "lua_api_generated.cpp" #include "generated_config.cpp" #include "draw.cpp" diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index b553920..483f692 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -250,8 +250,8 @@ void LayoutWindows(int16_t wx, int16_t wy) { Rect2 screen_rect = Rect0Size(wx, wy); Vec2 size = GetSize(screen_rect); - Rect2 a = CutLeft(&screen_rect, 0.3f * size.x); - Rect2 b = CutBottom(&a, 0.4f * size.y); + Rect2 a = CutRight(&screen_rect, 0.3f * size.x); + Rect2 b = CutTop(&a, 0.4f * size.y); Rect2 c = Shrink(b, 20); n->document_rect = n->total_rect = ToRect2I(c); } @@ -280,3 +280,40 @@ void LayoutWindows(int16_t wx, int16_t wy) { i += 1; } } + +Window *GetOverlappingWindow(Vec2I p, Window *default_window = NULL) { + For(Windows) { + if (AreOverlapping(p, it->total_rect)) { + return it; + } + } + return default_window; +} + +Vec2I GetSideOfWindow(Window *window, int direction) { + Vec2I p = {}; + Rect2I rect = window->total_rect; + float resizer_size = (float)window->font->char_spacing*0.5f; // @check_codebase_when_changing + if (direction == DIR_LEFT) { + p.x = rect.min.x - (Int)(resizer_size + window->font->char_spacing); + p.y = rect.min.y + (rect.max.y / 2); + } else if (direction == DIR_RIGHT) { + p.x = rect.max.x + (Int)(resizer_size + window->font->char_spacing); + p.y = rect.min.y + (rect.max.y / 2); + } else if (direction == DIR_UP) { + p.x = rect.min.x + (rect.max.x / 2); + p.y = rect.min.y - (Int)(resizer_size + window->font->line_spacing); + } else { + Assert(direction == DIR_DOWN); + p.x = rect.min.x + (rect.max.x / 2); + p.y = rect.max.y + (Int)(resizer_size + window->font->line_spacing); + } + return p; +} + +Window *SwitchWindow(int direction) { + Window *window = GetWindow(ActiveWindowID); + Vec2I p = GetSideOfWindow(window, direction); + Window *result = GetOverlappingWindow(p, window); + return result; +} diff --git a/src/text_editor/window.h b/src/text_editor/window.h index 696c29d..d63cbb2 100644 --- a/src/text_editor/window.h +++ b/src/text_editor/window.h @@ -34,6 +34,7 @@ struct Window { bool sync_visibility_with_focus : 1; bool lose_focus_on_escape : 1; bool jump_history : 1; + bool eval_command : 1; }; };