Compare commits

..

4 Commits

Author SHA1 Message Date
Krzosa Karol
29002c965c Commands and keybindings 2025-12-16 23:07:16 +01:00
Krzosa Karol
5e7acd4a20 Binding parser, TestFunctions 2025-12-15 23:29:18 +01:00
Krzosa Karol
4e5a0f6a9b Remove NextActiveWindowID 2025-12-14 23:08:22 +01:00
Krzosa Karol
f297006dcb RegisterLua and ShowCommands, continue refactor 2025-12-14 21:54:37 +01:00
19 changed files with 1309 additions and 902 deletions

View File

@@ -36,10 +36,34 @@ Commands TODO:
- Console: OK concept but constrain - Console: OK concept but constrain
- Turned off by default - Turned off by default
- Special: non editable, hotkeys don't work etc. - Special: non editable, hotkeys don't work etc.
- I'M SETTING ACTIVE WINDOW AFTER COMMAND!!! DO WE CONTINUE WITH THIS?
- CONSIDER AUTOMATING: CheckpointBeforeGoto
- GotoBackward how to handle that in case we want to automate and create on every move?
## Hooks and bindings
```
struct Hook {
String name;
String trigger;
HookFunction function;
};
void Command_New() {
...
} RegisterCommand(Command_New, "ctrl-n", NOT_VISIBLE_IN_LISTING);
// How do we handle Command_Delete variations????
void Hook_FormatOnSave() {
} RegisterHook(Hook_FormatOnSave, "onsave");
Array<Hook> Hooks;
```
DESIGN try to make console less special, make stuff reusable etc. DESIGN try to make console less special, make stuff reusable etc.

View File

@@ -37,8 +37,6 @@ For(arr.reverse_iter()) {
#define ForItem(it, array) for (auto &it : (array)) #define ForItem(it, array) for (auto &it : (array))
#define For(array) ForItem(it, array) #define For(array) ForItem(it, array)
template <class T> template <class T>
struct Slice { struct Slice {
T *data; T *data;

View File

@@ -213,3 +213,8 @@ inline uint64_t GetRandomU64(RandomSeed *state) {
x ^= x << 17; x ^= x << 17;
return state->a = x; return state->a = x;
} }
#define STRINGIFY_(x) x
#define STRINGIFY(x) STRINGIFY_(x)
#define CONCAT_(a, b) a ## b
#define CONCAT(a, b) CONCAT_(a, b)

View File

@@ -21,11 +21,11 @@ API void (*Error)(const char *, ...);
struct backtrace_state *backtrace_state = NULL; struct backtrace_state *backtrace_state = NULL;
void os_core_backtrace_error_callback(void *data, const char *msg, int errnum) { void BacktraceOnError(void *data, const char *msg, int errnum) {
Error("libbacktrace error: %s (errnum: %d)\n", msg, errnum); Error("libbacktrace error: %s (errnum: %d)\n", msg, errnum);
} }
int os_core_backtrace_print_callback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) { int BacktraceOnPrint(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) {
bool printed = false; bool printed = false;
if (filename != NULL) { if (filename != NULL) {
char buffer[512]; char buffer[512];
@@ -43,16 +43,16 @@ int os_core_backtrace_print_callback(void *data, uintptr_t pc, const char *filen
return 0; return 0;
} }
void os_unix_crash_handler(int signal, siginfo_t* info, void* context) { void CrashHandler(int signal, siginfo_t* info, void* context) {
backtrace_full(backtrace_state, 2, os_core_backtrace_print_callback, os_core_backtrace_error_callback, NULL); backtrace_full(backtrace_state, 2, BacktraceOnPrint, BacktraceOnError, NULL);
exit(1); exit(1);
} }
void os_unix_register_crash_handler(void) { void RegisterCrashHandler(void) {
backtrace_state = backtrace_create_state(NULL, 1, os_core_backtrace_error_callback, NULL); backtrace_state = backtrace_create_state(NULL, 1, BacktraceOnError, NULL);
struct sigaction sa; struct sigaction sa;
sa.sa_sigaction = os_unix_crash_handler; sa.sa_sigaction = CrashHandler;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO; sa.sa_flags = SA_RESTART | SA_SIGINFO;
@@ -65,7 +65,7 @@ void os_unix_register_crash_handler(void) {
API void InitOS(void (*error_proc)(const char *, ...)) { API void InitOS(void (*error_proc)(const char *, ...)) {
Error = error_proc; Error = error_proc;
os_unix_register_crash_handler(); RegisterCrashHandler();
} }
API String ReadFile(Allocator al, String path) { API String ReadFile(Allocator al, String path) {

View File

@@ -93,6 +93,16 @@ API Int GetBack(Caret caret) {
return result; return result;
} }
API Int GetMax(Caret caret) {
Int result = Max(caret.pos[0], caret.pos[1]);
return result;
}
API Int GetMin(Caret caret) {
Int result = Min(caret.pos[0], caret.pos[1]);
return result;
}
API Caret MakeCaret(Int pos) { API Caret MakeCaret(Int pos) {
Caret result = {}; Caret result = {};
result.range.min = result.range.max = pos; result.range.min = result.range.max = pos;
@@ -1223,7 +1233,7 @@ API Buffer *CreateTempBuffer(Allocator allocator, Int size = 4096) {
return result; return result;
} }
void RunBufferTest() { void RunBufferTest(void *param) {
{ {
Scratch scratch; Scratch scratch;
Buffer buffer = {}; Buffer buffer = {};
@@ -1400,7 +1410,7 @@ void RunBufferTest() {
DeinitBuffer(&buffer); DeinitBuffer(&buffer);
TrackingAllocatorCheck(); TrackingAllocatorCheck();
} }
} } RegisterFunction(&TestFunctions, RunBufferTest);
/////////////////////////////// ///////////////////////////////
// Management // Management

View File

@@ -222,7 +222,7 @@ void ReportErrorf(const char *fmt, ...) {
View *view = GetView(NullViewID); View *view = GetView(NullViewID);
if (view) { if (view) {
Appendf(view, "%S\n", string); Appendf(view, "%S\n", string);
NextActiveWindowID = NullWindowID; ActiveWindowID = NullWindowID;
} }
} }
@@ -613,15 +613,6 @@ void TrimTrailingWhitespace(Buffer *buffer, bool trim_lines_with_caret = false)
view->update_scroll = false; view->update_scroll = false;
} }
int Lua_TrimTrailingWhitespace(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});
TrimTrailingWhitespace(buffer, trim_lines_with_caret);
return 0;
}
void ConvertLineEndingsToLF(Buffer *buffer, bool trim_lines_with_caret = false) { void ConvertLineEndingsToLF(Buffer *buffer, bool trim_lines_with_caret = false) {
Scratch scratch; Scratch scratch;
@@ -654,15 +645,6 @@ void ConvertLineEndingsToLF(Buffer *buffer, bool trim_lines_with_caret = false)
view->update_scroll = 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) { void ApplyClangFormat(Buffer *buffer) {
Scratch scratch; Scratch scratch;
String string = AllocCharString(scratch, buffer); String string = AllocCharString(scratch, buffer);
@@ -670,22 +652,6 @@ void ApplyClangFormat(Buffer *buffer) {
ReplaceWithoutMovingCarets(buffer, GetRange(buffer), {temp_buffer->str, temp_buffer->len}); 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) { void SaveBuffer(Buffer *buffer) {
CallOnSave(buffer->id); CallOnSave(buffer->id);
@@ -702,29 +668,6 @@ void SaveBuffer(Buffer *buffer) {
} }
} }
void Command_Save() {
BSet active = GetBSet(LastActiveLayoutWindowID);
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) {
SaveBuffer(it);
}
}
} RegisterCommand(Command_SaveAll);
int Lua_SaveAll(lua_State *L) {
Command_SaveAll();
return 0;
}
void KillSelectedLines(View *view) { void KillSelectedLines(View *view) {
Scratch scratch; Scratch scratch;
Buffer *buffer = GetBuffer(view->active_buffer); Buffer *buffer = GetBuffer(view->active_buffer);
@@ -875,7 +818,7 @@ Caret FindPrev(Buffer *buffer, String16 needle, Caret caret) {
} }
Caret FindNext(Buffer *buffer, String16 needle, Caret caret) { Caret FindNext(Buffer *buffer, String16 needle, Caret caret) {
Int pos = GetFront(caret); Int pos = GetMax(caret);
String16 medium = GetString(buffer, {pos, INT64_MAX}); String16 medium = GetString(buffer, {pos, INT64_MAX});
Caret result = caret; Caret result = caret;
@@ -988,17 +931,6 @@ void ReopenBuffer(Buffer *buffer) {
buffer->dirty = false; buffer->dirty = false;
} }
void Command_Reopen() {
BSet main = GetBSet(LastActiveLayoutWindowID);
ReopenBuffer(main.buffer);
NextActiveWindowID = main.window->id;
} RegisterCommand(Command_Reopen);
int Lua_Reopen(lua_State *L) {
Command_Reopen();
return 0;
}
void New(Window *window, String name = "") { void New(Window *window, String name = "") {
View *view = GetView(window->active_view); View *view = GetView(window->active_view);
Buffer *buffer = GetBuffer(view->active_buffer); Buffer *buffer = GetBuffer(view->active_buffer);
@@ -1016,19 +948,6 @@ void New(Window *window, String name = "") {
WindowOpenBufferView(window, name); WindowOpenBufferView(window, name);
} }
void Command_New() {
BSet main = GetBSet(LastActiveLayoutWindowID);
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 = "") { void NewDir(Window *window, String name = "") {
View *view = GetView(window->active_view); View *view = GetView(window->active_view);
Buffer *buffer = GetBuffer(view->active_buffer); Buffer *buffer = GetBuffer(view->active_buffer);
@@ -1048,36 +967,6 @@ void NewDir(Window *window, String name = "") {
Open(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);
SDL_SetWindowPosition(SDLWindow, FullScreenPositionX, FullScreenPositionY);
} else {
SDL_GetWindowSize(SDLWindow, &FullScreenSizeX, &FullScreenSizeY);
SDL_GetWindowPosition(SDLWindow, &FullScreenPositionX, &FullScreenPositionY);
SDL_DisplayID display = SDL_GetDisplayForWindow(SDLWindow);
const SDL_DisplayMode *dm = SDL_GetCurrentDisplayMode(display);
SDL_SetWindowSize(SDLWindow, dm->w, dm->h);
SDL_SetWindowPosition(SDLWindow, 0, 0);
}
IsInFullscreen = !IsInFullscreen;
} RegisterCommand(Command_ToggleFullscreen);
int Lua_ToggleFullscreen(lua_State *L) {
Command_ToggleFullscreen();
return 0;
}
void ListFilesRecursive(Buffer *buffer, String dir) { void ListFilesRecursive(Buffer *buffer, String dir) {
Scratch scratch(buffer->line_starts.allocator); Scratch scratch(buffer->line_starts.allocator);
for (FileIter it = IterateFiles(scratch, dir); IsValid(it); Advance(&it)) { for (FileIter it = IterateFiles(scratch, dir); IsValid(it); Advance(&it)) {
@@ -1096,20 +985,6 @@ void ListFilesRecursive(Buffer *buffer, String dir) {
} }
} }
void Command_ListCode() {
BSet main = GetBSet(LastActiveLayoutWindowID);
JumpGarbageBuffer(&main);
ListFilesRecursive(main.buffer, WorkDir);
main.view->fuzzy_search = true;
main.view->update_scroll = true;
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 *ExecHidden(String buffer_name, String cmd, String working_dir) {
View *view = OpenBufferView(buffer_name); View *view = OpenBufferView(buffer_name);
Exec(view->id, true, cmd, working_dir); Exec(view->id, true, cmd, working_dir);
@@ -1119,20 +994,13 @@ View *ExecHidden(String buffer_name, String cmd, String working_dir) {
BSet Exec(String cmd, String working_dir, bool set_active = true) { BSet Exec(String cmd, String working_dir, bool set_active = true) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
if (set_active) { if (set_active) {
NextActiveWindowID = main.window->id; ActiveWindowID = main.window->id;
} }
JumpGarbageBuffer(&main); JumpGarbageBuffer(&main);
Exec(main.view->id, true, cmd, working_dir); Exec(main.view->id, true, cmd, working_dir);
return main; 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) { BSet Open(Window *window, String path, String meta, bool set_active = true) {
Scratch scratch; Scratch scratch;
BSet set = GetBSet(window); BSet set = GetBSet(window);
@@ -1140,7 +1008,7 @@ BSet Open(Window *window, String path, String meta, bool set_active = true) {
OnOpenResult ores = CallOnOpen(scratch, path, meta); OnOpenResult ores = CallOnOpen(scratch, path, meta);
if (ores.kind == "text") { if (ores.kind == "text") {
if (set_active) { if (set_active) {
NextActiveWindowID = set.window->id; ActiveWindowID = set.window->id;
} }
if (IsDir(ores.file_path)) { if (IsDir(ores.file_path)) {
JumpGarbageBuffer(&set, GetUniqueBufferName(ores.file_path, "temp", ".dirlisting")); JumpGarbageBuffer(&set, GetUniqueBufferName(ores.file_path, "temp", ".dirlisting"));
@@ -1161,7 +1029,7 @@ BSet Open(Window *window, String path, String meta, bool set_active = true) {
UpdateScroll(set.window, true); UpdateScroll(set.window, true);
} else if (ores.kind == "exec") { } else if (ores.kind == "exec") {
if (set_active) { if (set_active) {
NextActiveWindowID = set.window->id; ActiveWindowID = set.window->id;
} }
JumpGarbageBuffer(&set); JumpGarbageBuffer(&set);
Exec(set.view->id, true, ores.cmd, ores.working_dir); Exec(set.view->id, true, ores.cmd, ores.working_dir);
@@ -1190,103 +1058,6 @@ BSet Open(String16 path, String meta) {
return Open(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;
NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
For(Buffers) {
RawAppendf(command_bar.buffer, "%-80S || %S\n", SkipToLastSlash(it->name), it->name);
}
command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowBufferList);
void Command_ShowCommandList() {
BSet command_bar = GetBSet(CommandBarWindowID);
command_bar.window->visible = true;
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);
}
command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowCommandList);
void Command_ListViews() {
BSet command_bar = GetBSet(CommandBarWindowID);
command_bar.window->visible = true;
NextActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
For(Views) {
Buffer *buffer = GetBuffer(it->active_buffer);
Appendf(command_bar.view, "%d %S\n", (int)it->id.id, buffer->name);
}
command_bar.view->fuzzy_search = true;
command_bar.view->update_scroll = true;
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) { void Eval(String string) {
if (luaL_dostring(LuaState, string.data) != LUA_OK) { if (luaL_dostring(LuaState, string.data) != LUA_OK) {
const char *error_message = lua_tostring(LuaState, -1); const char *error_message = lua_tostring(LuaState, -1);
@@ -1300,26 +1071,104 @@ void Eval(String16 string) {
Eval(ToString(scratch, 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) { void SetProjectFile(Buffer *buffer) {
WorkDir = ChopLastSlash(buffer->name); WorkDir = ChopLastSlash(buffer->name);
LuaProjectBuffer = buffer; LuaProjectBuffer = buffer;
LuaProjectBuffer->user_change_id = -1; LuaProjectBuffer->user_change_id = -1;
} }
void Command_SetProjectFile() { String16 FetchLoadWord(BSet set) {
Caret caret = set.view->carets[0];
Range range = caret.range;
if (GetSize(caret.range) == 0) range = EncloseLoadWord(set.buffer, GetFront(caret));
String16 string = GetString(set.buffer, range);
return string;
}
void Command_Save(CommandContext *ctx) {
BSet active = GetBSet(LastActiveLayoutWindowID);
SaveBuffer(active.buffer);
} RegisterCommand(Command_Save, "ctrl-s");
void Command_SaveAll(CommandContext *ctx) {
For(Buffers) {
if (it->file_mod_time) {
SaveBuffer(it);
}
}
} RegisterCommand(Command_SaveAll, "ctrl-shift-s");
void Command_Reopen(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID);
ReopenBuffer(main.buffer);
ActiveWindowID = main.window->id;
} RegisterCommand(Command_Reopen, "");
void Command_New(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID);
New(main.window, "");
} RegisterCommand(Command_New, "ctrl-n");
void Command_ToggleFullscreen(CommandContext *ctx) {
if (IsInFullscreen) {
SDL_SetWindowSize(SDLWindow, FullScreenSizeX, FullScreenSizeY);
SDL_SetWindowPosition(SDLWindow, FullScreenPositionX, FullScreenPositionY);
} else {
SDL_GetWindowSize(SDLWindow, &FullScreenSizeX, &FullScreenSizeY);
SDL_GetWindowPosition(SDLWindow, &FullScreenPositionX, &FullScreenPositionY);
SDL_DisplayID display = SDL_GetDisplayForWindow(SDLWindow);
const SDL_DisplayMode *dm = SDL_GetCurrentDisplayMode(display);
SDL_SetWindowSize(SDLWindow, dm->w, dm->h);
SDL_SetWindowPosition(SDLWindow, 0, 0);
}
IsInFullscreen = !IsInFullscreen;
} RegisterCommand(Command_ToggleFullscreen, "f11");
void Command_ListCode(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID);
JumpGarbageBuffer(&main);
ListFilesRecursive(main.buffer, WorkDir);
main.view->fuzzy_search = true;
main.view->update_scroll = true;
SelectRange(main.view, GetBufferEndAsRange(main.buffer));
} RegisterCommand(Command_ListCode, "");
void Command_ShowBufferList(CommandContext *ctx) {
BSet command_bar = GetBSet(CommandBarWindowID);
command_bar.window->visible = true;
command_bar.window->eval_command = false;
ActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
For(Buffers) {
RawAppendf(command_bar.buffer, "%-80S || %S\n", SkipToLastSlash(it->name), it->name);
}
command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer));
} RegisterCommand(Command_ShowBufferList, "ctrl-p");
void Command_ListViews(CommandContext *ctx) {
BSet command_bar = GetBSet(CommandBarWindowID);
command_bar.window->visible = true;
command_bar.window->eval_command = false;
ActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
For(Views) {
Buffer *buffer = GetBuffer(it->active_buffer);
Appendf(command_bar.view, "%d %S\n", (int)it->id.id, buffer->name);
}
command_bar.view->fuzzy_search = true;
command_bar.view->update_scroll = true;
SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer));
} RegisterCommand(Command_ListViews, "");
void Command_SetProjectFile(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
SetProjectFile(main.buffer); SetProjectFile(main.buffer);
} RegisterCommand(Command_SetProjectFile); } RegisterCommand(Command_SetProjectFile, "");
void Command_SetWorkDir() { void Command_SetWorkDir(CommandContext *ctx) {
String dir = lua_tostring(LuaState, -1); String dir = lua_tostring(LuaState, -1);
if (dir.len == 0) { if (dir.len == 0) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
@@ -1327,117 +1176,435 @@ void Command_SetWorkDir() {
} else { } else {
WorkDir = dir; WorkDir = dir;
} }
} } RegisterCommand(Command_SetWorkDir, "");
void Command_SetProject() { void Command_SetProject(CommandContext *ctx) {
Command_SetWorkDir(); Command_SetWorkDir(ctx);
Command_SetProjectFile(); Command_SetProjectFile(ctx);
} RegisterCommand(Command_SetProject); } RegisterCommand(Command_SetProject, "");
int Lua_SetProjectFile(lua_State *L) { void Command_ToggleDebug(CommandContext *ctx) {
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];
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_ToggleDebug() {
Window *window = GetWindow(DebugWindowID); Window *window = GetWindow(DebugWindowID);
window->visible = !window->visible; window->visible = !window->visible;
} RegisterCommand(Command_ToggleDebug); } RegisterCommand(Command_ToggleDebug, "ctrl-0");
void Command_KillProcess() { void Command_KillProcess(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
KillProcess(main.view); KillProcess(main.view);
} RegisterCommand(Command_KillProcess); } RegisterCommand(Command_KillProcess, "");
int Lua_KillProcess(lua_State *L) { void Command_KillWindow(CommandContext *ctx) {
Command_KillProcess();
return 0;
}
void Command_KillWindow() {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
main.window->kill = true; main.window->kill = true;
} RegisterCommand(Command_KillWindow); } RegisterCommand(Command_KillWindow, "ctrl-w");
int Lua_KillWindow(lua_State *L) { void Command_ShowCommands(CommandContext *ctx) {
Command_KillWindow(); BSet command_bar = GetBSet(CommandBarWindowID);
return 0; command_bar.window->visible = true;
command_bar.window->eval_command = true;
ActiveWindowID = 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, "ctrl-shift-p");
void Command_ShowLuaFunctions(CommandContext *ctx) {
BSet command_bar = GetBSet(CommandBarWindowID);
command_bar.window->visible = true;
command_bar.window->eval_command = false;
ActiveWindowID = command_bar.window->id;
ResetBuffer(command_bar.buffer);
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_ShowLuaFunctions, "");
void Command_GotoBackward(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID);
GotoBackward(main.window);
} RegisterCommand(Command_GotoBackward, "alt-q | mousex1");
void Command_GotoForward(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID);
GotoForward(main.window);
} RegisterCommand(Command_GotoForward, "mousex2");
void Command_OpenUpFolder(CommandContext *ctx) {
BSet main = GetBSet(LastActiveLayoutWindowID);
String name = ChopLastSlash(main.buffer->name);
if (EndsWith(main.buffer->name, "dirlisting")) {
name = ChopLastSlash(name);
}
Open(name);
} RegisterCommand(Command_OpenUpFolder, "ctrl-period");
void Command_EncloseLine(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
EncloseLine(active.view);
} RegisterCommand(Command_EncloseLine, "ctrl-l");
void Command_SelectAll(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
SelectEntireBuffer(active.view);
active.view->update_scroll = false;
} RegisterCommand(Command_SelectAll, "ctrl-a");
void Command_Redo(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
RedoEdit(active.buffer, &active.view->carets);
} RegisterCommand(Command_Redo, "ctrl-shift-z");
void Command_Undo(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
UndoEdit(active.buffer, &active.view->carets);
} RegisterCommand(Command_Undo, "ctrl-z");
void Command_MakeFontLarger(CommandContext *ctx) {
StyleFontSize += 1;
ReloadFont(StyleFont, (U32)StyleFontSize);
} RegisterCommand(Command_MakeFontLarger, "ctrl-equals");
void Command_MakeFontSmaller(CommandContext *ctx) {
if (StyleFontSize > 4) {
StyleFontSize -= 1;
ReloadFont(StyleFont, (U32)StyleFontSize);
}
} RegisterCommand(Command_MakeFontSmaller, "ctrl-minus");
void Command_Search(CommandContext *ctx) {
Window *window = GetWindow(SearchBarWindowID);
window->visible = !window->visible;
} RegisterCommand(Command_Search, "ctrl-f");
void EvalCommand(CommandContext *ctx, String command) {
For (CommandFunctions) {
if (it.name == command) {
it.function(ctx);
break;
}
}
} }
void EvalCommand(CommandContext *ctx, String16 command) {
Scratch scratch;
EvalCommand(ctx, ToString(scratch, command));
}
void FuzzySearchOpen(CommandContext *ctx, BSet active) {
Range range = active.view->carets[0].range;
String16 string = FetchLoadWord(active);
if (GetSize(range) == 0) {
Int line = PosToLine(active.buffer, range.min);
if ((active.buffer->line_starts.len - 1) == line) {
line = ClampBottom(0ll, line - 1ll);
}
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);
ActiveWindowID = main.window->id;
EvalCommand(ctx, string);
} else {
Open(string);
}
}
void Command_Open(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
if (active.view->fuzzy_search) {
FuzzySearchOpen(ctx, active);
} else {
BSet active = GetBSet(LastActiveLayoutWindowID);
Open(FetchLoadWord(active));
}
} RegisterCommand(Command_Open, "ctrl-q");
void Command_KillSelectedLines(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
KillSelectedLines(active.view);
} RegisterCommand(Command_KillSelectedLines, "ctrl-shift-k");
void Command_IndentSelectedLines(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
Event event = *OnCommandEvent;
bool left = false;
if (Press(SDLK_LEFTBRACKET) || ShiftPress(SDLK_TAB)) {
left = true;
}
IndentSelectedLines(active.view, left);
} RegisterCommand(Command_IndentSelectedLines, "ctrl-leftbracket | ctrl-rightbracket | tab | shift-tab");
void Command_DuplicateLineDown(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
DuplicateLine(active.view, DIR_DOWN);
} RegisterCommand(Command_DuplicateLineDown, "ctrl-alt-down");
void Command_CreateCursorDown(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
CreateCursorVertical(active.view, DIR_DOWN);
} RegisterCommand(Command_CreateCursorDown, "alt-shift-down");
void Command_SelectDownToEmptyLine(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_DOWN, CTRL_PRESSED, SHIFT_PRESS);
} RegisterCommand(Command_SelectDownToEmptyLine, "ctrl-shift-down");
void Command_MoveLineDown(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCaretsLine(active.view, DIR_DOWN);
} RegisterCommand(Command_MoveLineDown, "alt-down");
void Command_MoveDownToEmptyLine(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_DOWN, CTRL_PRESSED);
} RegisterCommand(Command_MoveDownToEmptyLine, "ctrl-down");
void Command_SelectDown(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_DOWN, false, SHIFT_PRESS);
} RegisterCommand(Command_SelectDown, "shift-down");
void Command_MoveDown(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_DOWN);
} RegisterCommand(Command_MoveDown, "down");
void Command_DuplicateLineUp(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
DuplicateLine(active.view, DIR_UP);
} RegisterCommand(Command_DuplicateLineUp, "ctrl-alt-up");
void Command_CreateCursorUp(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
CreateCursorVertical(active.view, DIR_UP);
} RegisterCommand(Command_CreateCursorUp, "alt-shift-up");
void Command_SelectUpToEmptyLine(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_UP, CTRL_PRESSED, SHIFT_PRESS);
} RegisterCommand(Command_SelectUpToEmptyLine, "ctrl-shift-up");
void Command_MoveLineUp(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCaretsLine(active.view, DIR_UP);
} RegisterCommand(Command_MoveLineUp, "alt-up");
void Command_MoveUpToEmptyLine(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_UP, CTRL_PRESSED);
} RegisterCommand(Command_MoveUpToEmptyLine, "ctrl-up");
void Command_SelectUp(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_UP, false, SHIFT_PRESS);
} RegisterCommand(Command_SelectUp, "shift-up");
void Command_MoveUp(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_UP);
} RegisterCommand(Command_MoveUp, "up");
void Command_BoundarySelectLeft(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_LEFT, CTRL_PRESSED, SHIFT_PRESS);
} RegisterCommand(Command_BoundarySelectLeft, "ctrl-shift-left");
void Command_BoundaryMoveLeft(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_LEFT, CTRL_PRESSED);
} RegisterCommand(Command_BoundaryMoveLeft, "ctrl-left");
void Command_SelectLeft(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_LEFT, false, SHIFT_PRESS);
} RegisterCommand(Command_SelectLeft, "shift-left");
void Command_FocusLeftWindow(CommandContext *ctx) {
ActiveWindowID = SwitchWindow(DIR_LEFT)->id;
} RegisterCommand(Command_FocusLeftWindow, "alt-left");
void Command_MoveLeft(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_LEFT);
} RegisterCommand(Command_MoveLeft, "left");
void Command_BoundarySelectRight(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_RIGHT, CTRL_PRESSED, SHIFT_PRESS);
} RegisterCommand(Command_BoundarySelectRight, "ctrl-shift-right");
void Command_BoundaryMoveRight(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_RIGHT, CTRL_PRESSED);
} RegisterCommand(Command_BoundaryMoveRight, "ctrl-right");
void Command_SelectRight(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_RIGHT, false, SHIFT_PRESS);
} RegisterCommand(Command_SelectRight, "shift-right");
void Command_FocusRightWindow(CommandContext *ctx) {
ActiveWindowID = SwitchWindow(DIR_RIGHT)->id;
} RegisterCommand(Command_FocusRightWindow, "alt-right");
void Command_MoveRight(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCarets(active.view, DIR_RIGHT);
} RegisterCommand(Command_MoveRight, "right");
void Command_MoveUpAPage(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorByPageSize(active.window, DIR_UP, SHIFT_PRESS);
} RegisterCommand(Command_MoveUpAPage, "pageup");
void Command_SelectDownPage(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorByPageSize(active.window, DIR_DOWN, SHIFT_PRESS);
} RegisterCommand(Command_SelectDownPage, "shift-pagedown");
void Command_MoveToEnd(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
SelectRange(active.view, MakeRange(active.buffer->len));
} RegisterCommand(Command_MoveToEnd, "pagedown");
void Command_MoveDownPage(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
SelectRange(active.view, MakeRange(active.buffer->len));
} RegisterCommand(Command_MoveDownPage, "ctrl-pagedown");
void Command_SelectUpPage(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorByPageSize(active.window, DIR_UP, SHIFT_PRESS);
} RegisterCommand(Command_SelectUpPage, "shift-pageup");
void Command_MoveToStart(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
SelectRange(active.view, MakeRange(0));
} RegisterCommand(Command_MoveToStart, "ctrl-pageup");
void Command_MoveUpPage(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorByPageSize(active.window, DIR_UP);
} RegisterCommand(Command_MoveUpPage, "pageup");
void Command_SelectToLineStart(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorToSide(active.view, DIR_LEFT, SHIFT_PRESS);
} RegisterCommand(Command_SelectToLineStart, "shift-home");
void Command_MoveToLineStart(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorToSide(active.view, DIR_LEFT);
} RegisterCommand(Command_MoveToLineStart, "home");
void Command_MoveToLineEnd(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorToSide(active.view, DIR_RIGHT);
} RegisterCommand(Command_MoveToLineEnd, "end");
void Command_SelectToLineEnd(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorToSide(active.view, DIR_RIGHT, SHIFT_PRESS);
} RegisterCommand(Command_SelectToLineEnd, "shift-end");
void Command_Delete(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
Delete(active.view, DIR_LEFT);
} RegisterCommand(Command_Delete, "backspace");
void Command_DeleteBoundary(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
Delete(active.view, DIR_LEFT, SHIFT_PRESS);
} RegisterCommand(Command_DeleteBoundary, "ctrl-backspace");
void Command_DeleteForward(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
Delete(active.view, DIR_RIGHT);
} RegisterCommand(Command_DeleteForward, "delete");
void Command_DeleteForwardBoundary(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
Delete(active.view, DIR_RIGHT, SHIFT_PRESS);
} RegisterCommand(Command_DeleteForwardBoundary, "ctrl-delete");
void Command_InsertNewLineUp(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorToSide(active.view, DIR_LEFT);
IdentedNewLine(active.view);
MoveCarets(active.view, DIR_UP);
} RegisterCommand(Command_InsertNewLineUp, "ctrl-shift-enter");
void Command_InsertNewLineDown(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
MoveCursorToSide(active.view, DIR_RIGHT);
IdentedNewLine(active.view);
} RegisterCommand(Command_InsertNewLineDown, "ctrl-enter");
void Command_SelectFuzzySearchEntry(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
if (active.view->fuzzy_search) {
FuzzySearchOpen(ctx, active);
ctx->out_skip_rem_cmds = true;
}
} RegisterCommand(Command_SelectFuzzySearchEntry, "enter");
void Command_NewLine(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
IdentedNewLine(active.view);
} RegisterCommand(Command_NewLine, "enter");
void Command_CreateCaretOnNextFind(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
String16 string = GetString(active.buffer, active.view->carets[0].range);
Caret caret = FindNext(active.buffer, string, active.view->carets[0]);
Insert(&active.view->carets, caret, 0);
MergeCarets(active.buffer, &active.view->carets);
} RegisterCommand(Command_CreateCaretOnNextFind, "ctrl-d");
void Command_FocusWindow1(CommandContext *ctx) {
ActiveWindowID = GetOverlappingWindow({0,0}, GetWindow(ActiveWindowID))->id;
} RegisterCommand(Command_FocusWindow1, "ctrl-1");
void Command_FocusWindow2(CommandContext *ctx) {
Window *first = GetOverlappingWindow({0,0}, GetWindow(ActiveWindowID));
Vec2I p = GetSideOfWindow(first, DIR_RIGHT);
ActiveWindowID = GetOverlappingWindow(p, GetWindow(ActiveWindowID))->id;
} RegisterCommand(Command_FocusWindow2, "ctrl-2");
void Command_FocusWindow3(CommandContext *ctx) {
Window *first = GetOverlappingWindow({0,0});
if (first) {
Window *second = GetOverlappingWindow(GetSideOfWindow(first, DIR_RIGHT));
if (second) {
Window *third = GetOverlappingWindow(GetSideOfWindow(second, DIR_RIGHT));
if (third) {
ActiveWindowID = third->id;
}
}
}
} RegisterCommand(Command_FocusWindow3, "ctrl-3");
void Command_ClearCarets(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
active.view->carets.len = 1;
active.view->carets[0] = MakeCaret(GetFront(active.view->carets[0]));
// @todo: move to hook post command???
if (active.window->lose_focus_on_escape && active.window->id == ActiveWindowID) {
if (active.window->layout) {
//
} else {
ActiveWindowID = LastActiveLayoutWindowID;
}
}
} RegisterCommand(Command_ClearCarets, "escape");

View File

@@ -46,29 +46,6 @@ void UpdateScroll(Window *window, bool update_caret_scrolling) {
} }
} }
void FuzzySearchOpen(BSet active) {
bool success = false;
Range range = active.view->carets[0].range;
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);
Int idx = 0;
if (Seek(string, u"||", &idx)) {
string = Skip(string, idx + 3);
Open(string);
success = true;
}
}
if (!success) {
Open(FetchLoadWord());
}
}
void OnCommand(Event event) { void OnCommand(Event event) {
ProfileFunction(); ProfileFunction();
// //
@@ -179,21 +156,12 @@ void OnCommand(Event event) {
} }
bool mouse_in_document = AreOverlapping(mouse, it->document_rect); bool mouse_in_document = AreOverlapping(mouse, it->document_rect);
if (mouse_in_document) { if (mouse_in_document) {
NextActiveWindowID = it->id; ActiveWindowID = it->id;
break; break;
} }
} }
} }
if (Mouse(X2)) {
BSet main = GetBSet(LastActiveLayoutWindowID);
GotoForward(main.window);
}
if (Mouse(X1)) {
BSet main = GetBSet(LastActiveLayoutWindowID);
GotoBackward(main.window);
}
if (Ctrl() && Shift() && Mouse(RIGHT)) { if (Ctrl() && Shift() && Mouse(RIGHT)) {
} else if (Alt() && Ctrl() && Mouse(RIGHT)) { } else if (Alt() && Ctrl() && Mouse(RIGHT)) {
@@ -237,7 +205,7 @@ void OnCommand(Event event) {
Assert(ScrollbarSelected.id == -1); Assert(ScrollbarSelected.id == -1);
Assert(DocumentSelected.id == -1); Assert(DocumentSelected.id == -1);
BSet active = GetBSet(NextActiveWindowID); // using next to make sure mouse works on first click after switching the window BSet active = GetBSet(ActiveWindowID); // using next to make sure mouse works on first click after switching the window
bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect); bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect);
bool mouse_in_line_numbers = AreOverlapping(mouse, active.window->line_numbers_rect); bool mouse_in_line_numbers = AreOverlapping(mouse, active.window->line_numbers_rect);
if (mouse_in_document || mouse_in_line_numbers) { if (mouse_in_document || mouse_in_line_numbers) {
@@ -298,215 +266,28 @@ void OnCommand(Event event) {
} }
} }
if (CtrlPress(SDLK_W)) { BSet main = GetBSet(LastActiveLayoutWindowID);
Command_KillWindow(); BSet active = GetBSet(ActiveWindowID);
} Int buffer_change_id = active.buffer->change_id;
CommandContext ctx = {};
if (CtrlAltPress(SDLK_P)) { For (CommandFunctions) {
} else if (CtrlShiftPress(SDLK_P)) { if (it.trigger && MatchEvent(it.trigger, &event)) {
Command_ShowCommandList(); it.function(&ctx);
} else if (CtrlPress(SDLK_P)) { MergeCarets(active.buffer, &active.view->carets);
Command_ShowBufferList(); IF_DEBUG(AssertRanges(active.view->carets));
} if (ctx.out_skip_rem_cmds) {
return;
if (CtrlPress(SDLK_0)) {
Command_ToggleDebug();
}
if (CtrlPress(SDLK_1)) {
NextActiveWindowID = GetOverlappingWindow({0,0}, GetWindow(ActiveWindowID))->id;
}
if (CtrlPress(SDLK_2)) {
Window *first = GetOverlappingWindow({0,0}, GetWindow(ActiveWindowID));
Vec2I p = GetSideOfWindow(first, DIR_RIGHT);
NextActiveWindowID = GetOverlappingWindow(p, GetWindow(ActiveWindowID))->id;
}
if (CtrlPress(SDLK_3)) {
Window *first = GetOverlappingWindow({0,0});
if (first) {
Window *second = GetOverlappingWindow(GetSideOfWindow(first, DIR_RIGHT));
if (second) {
Window *third = GetOverlappingWindow(GetSideOfWindow(second, DIR_RIGHT));
if (third) {
NextActiveWindowID = third->id;
}
} }
} }
} }
BSet main = GetBSet(LastActiveLayoutWindowID); // @todo: do we need the context for commands, maybe skip cmds should be global?
BSet active = GetBSet(ActiveWindowID); // @todo: hook drop file
Int buffer_change_id = active.buffer->change_id;
bool skip = CallOnCommand(&event);
if (skip) {
// :OnCommandEnding
MergeCarets(active.buffer, &active.view->carets);
IF_DEBUG(AssertRanges(active.view->carets));
return;
}
if (active.view->fuzzy_search) {
if (Press(SDLK_RETURN)) {
FuzzySearchOpen(active);
return;
}
}
if (event.kind == EVENT_DROP_FILE) { if (event.kind == EVENT_DROP_FILE) {
WindowOpenBufferView(active.window, event.text); WindowOpenBufferView(active.window, event.text);
} }
if (Press(SDLK_DOWN) || Press(SDLK_RIGHT) || Press(SDLK_LEFT) || Press(SDLK_UP)) { // @todo: hook on textinput
CheckpointBeforeGoto(active.window);
}
if (CtrlAltPress(SDLK_DOWN)) {
DuplicateLine(active.view, DIR_DOWN);
} else if (AltShiftPress(SDLK_DOWN)) {
CreateCursorVertical(active.view, DIR_DOWN);
} else if (CtrlShiftPress(SDLK_DOWN)) {
MoveCarets(active.view, DIR_DOWN, CTRL_PRESSED, SHIFT_PRESS);
} else if (AltPress(SDLK_DOWN)) {
MoveCaretsLine(active.view, DIR_DOWN);
} else if (CtrlPress(SDLK_DOWN)) {
MoveCarets(active.view, DIR_DOWN, CTRL_PRESSED);
} else if (ShiftPress(SDLK_DOWN)) {
MoveCarets(active.view, DIR_DOWN, false, SHIFT_PRESS);
} else if (Press(SDLK_DOWN)) {
MoveCarets(active.view, DIR_DOWN);
}
if (CtrlAltPress(SDLK_UP)) {
DuplicateLine(active.view, DIR_UP);
} else if (AltShiftPress(SDLK_UP)) {
CreateCursorVertical(active.view, DIR_UP);
} else if (CtrlShiftPress(SDLK_UP)) {
MoveCarets(active.view, DIR_UP, CTRL_PRESSED, SHIFT_PRESS);
} else if (AltPress(SDLK_UP)) {
MoveCaretsLine(active.view, DIR_UP);
} else if (CtrlPress(SDLK_UP)) {
MoveCarets(active.view, DIR_UP, CTRL_PRESSED);
} else if (ShiftPress(SDLK_UP)) {
MoveCarets(active.view, DIR_UP, false, SHIFT_PRESS);
} else if (Press(SDLK_UP)) {
MoveCarets(active.view, DIR_UP);
}
if (CtrlShiftPress(SDLK_LEFT)) {
MoveCarets(active.view, DIR_LEFT, CTRL_PRESSED, SHIFT_PRESS);
} else if (CtrlPress(SDLK_LEFT)) {
MoveCarets(active.view, DIR_LEFT, CTRL_PRESSED);
} else if (ShiftPress(SDLK_LEFT)) {
MoveCarets(active.view, DIR_LEFT, false, SHIFT_PRESS);
} else if (AltPress(SDLK_LEFT)) {
NextActiveWindowID = SwitchWindow(DIR_LEFT)->id;
} else if (Press(SDLK_LEFT)) {
MoveCarets(active.view, DIR_LEFT);
}
if (CtrlShiftPress(SDLK_RIGHT)) {
MoveCarets(active.view, DIR_RIGHT, CTRL_PRESSED, SHIFT_PRESS);
} else if (CtrlPress(SDLK_RIGHT)) {
MoveCarets(active.view, DIR_RIGHT, CTRL_PRESSED);
} else if (ShiftPress(SDLK_RIGHT)) {
MoveCarets(active.view, DIR_RIGHT, false, SHIFT_PRESS);
} else if (AltPress(SDLK_RIGHT)) {
NextActiveWindowID = SwitchWindow(DIR_RIGHT)->id;
} else if (Press(SDLK_RIGHT)) {
MoveCarets(active.view, DIR_RIGHT);
}
if (CtrlShiftPress(SDLK_Z)) {
RedoEdit(active.buffer, &active.view->carets);
} else if (CtrlPress(SDLK_Z)) {
UndoEdit(active.buffer, &active.view->carets);
}
if (CtrlPress(SDLK_C)) {
ClipboardCopy(active.view);
} else if (CtrlPress(SDLK_V)) {
ClipboardPaste(active.view);
} else if (CtrlPress(SDLK_X)) {
SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets);
ClipboardCopy(active.view);
Replace(active.view, u"");
}
if (CtrlPress(SDLK_A)) {
SelectEntireBuffer(active.view);
active.view->update_scroll = false;
}
if (ShiftPress(SDLK_PAGEUP)) {
CheckpointBeforeGoto(active.window);
MoveCursorByPageSize(active.window, DIR_UP, SHIFT_PRESS);
} else if (CtrlPress(SDLK_PAGEUP)) {
CheckpointBeforeGoto(active.window);
SelectRange(active.view, MakeRange(0));
} else if (Press(SDLK_PAGEUP)) {
CheckpointBeforeGoto(active.window);
MoveCursorByPageSize(active.window, DIR_UP);
}
if (ShiftPress(SDLK_PAGEDOWN)) {
CheckpointBeforeGoto(active.window);
MoveCursorByPageSize(active.window, DIR_DOWN, SHIFT_PRESS);
} else if (CtrlPress(SDLK_PAGEDOWN)) {
CheckpointBeforeGoto(active.window);
SelectRange(active.view, MakeRange(active.buffer->len));
} else if (Press(SDLK_PAGEDOWN)) {
CheckpointBeforeGoto(active.window);
MoveCursorByPageSize(active.window, DIR_DOWN);
}
if (ShiftPress(SDLK_HOME)) {
CheckpointBeforeGoto(active.window);
MoveCursorToSide(active.view, DIR_LEFT, SHIFT_PRESS);
} else if (Press(SDLK_HOME)) {
CheckpointBeforeGoto(active.window);
MoveCursorToSide(active.view, DIR_LEFT);
}
if (ShiftPress(SDLK_END)) {
CheckpointBeforeGoto(active.window);
MoveCursorToSide(active.view, DIR_RIGHT, SHIFT_PRESS);
} else if (Press(SDLK_END)) {
CheckpointBeforeGoto(active.window);
MoveCursorToSide(active.view, DIR_RIGHT);
}
if (CtrlShiftPress(SDLK_TAB)) {
} else if (ShiftPress(SDLK_TAB)) {
IndentSelectedLines(active.view, SHIFT_PRESS);
} else if (CtrlPress(SDLK_TAB)) {
} else if (Press(SDLK_TAB)) {
IndentSelectedLines(active.view);
}
if (CtrlPress(SDLK_LEFTBRACKET)) {
IndentSelectedLines(active.view, SHIFT_PRESS);
}
if (CtrlPress(SDLK_RIGHTBRACKET)) {
IndentSelectedLines(active.view);
}
if (CtrlShiftPress(SDLK_K)) {
KillSelectedLines(active.view);
}
if (CtrlPress(SDLK_BACKSPACE)) {
Delete(active.view, DIR_LEFT, CTRL_PRESSED);
} else if (Press(SDLK_BACKSPACE)) {
Delete(active.view, DIR_LEFT);
}
if (CtrlPress(SDLK_DELETE)) {
Delete(active.view, DIR_RIGHT, CTRL_PRESSED);
} else if (Press(SDLK_DELETE)) {
Delete(active.view, DIR_RIGHT);
}
if (event.kind == EVENT_TEXT_INPUT) { if (event.kind == EVENT_TEXT_INPUT) {
Scratch scratch; Scratch scratch;
String string = event.text; String string = event.text;
@@ -514,45 +295,12 @@ void OnCommand(Event event) {
Replace(active.view, string16); Replace(active.view, string16);
} }
if (CtrlPress(SDLK_D)) { // @todo: hook PostCommand?
CheckpointBeforeGoto(active.window); // @todo: Detect if edited
String16 string = GetString(active.buffer, active.view->carets[0].range);
Caret caret = FindNext(active.buffer, string, active.view->carets[0]);
Insert(&active.view->carets, caret, 0);
MergeCarets(active.buffer, &active.view->carets);
}
if (CtrlPress(SDLK_EQUALS)) {
StyleFontSize += 1;
ReloadFont(StyleFont, (U32)StyleFontSize);
}
if (CtrlPress(SDLK_MINUS)) {
if (StyleFontSize > 4) {
StyleFontSize -= 1;
ReloadFont(StyleFont, (U32)StyleFontSize);
}
}
if (CtrlPress(SDLK_E)) {
} else if (AltPress(SDLK_E)) {
}
if (CtrlShiftPress(SDLK_RETURN)) {
MoveCursorToSide(active.view, DIR_LEFT);
IdentedNewLine(active.view);
MoveCarets(active.view, DIR_UP);
} else if (CtrlPress(SDLK_RETURN)) {
MoveCursorToSide(active.view, DIR_RIGHT);
IdentedNewLine(active.view);
} else if (Press(SDLK_RETURN)) {
IdentedNewLine(active.view);
}
if (active.view->fuzzy_search) { if (active.view->fuzzy_search) {
if (!ProcessIsActive(active.view->id)) { if (!ProcessIsActive(active.view->id)) {
Scratch scratch; Scratch scratch;
String16 last_line_string = GetLineStringWithoutNL(active.buffer, active.buffer->line_starts.len - 1); String16 last_line_string = GetLineStringWithoutNL(active.buffer, active.buffer->line_starts.len - 1);
if (active.view->prev_search_line != last_line_string) { if (active.view->prev_search_line != last_line_string) {
active.view->prev_search_line = last_line_string; active.view->prev_search_line = last_line_string;
Array<FuzzyPair> ratings = FuzzySearchLines(scratch, active.buffer, 0, active.buffer->line_starts.len - 1, last_line_string); Array<FuzzyPair> ratings = FuzzySearchLines(scratch, active.buffer, 0, active.buffer->line_starts.len - 1, last_line_string);
@@ -575,60 +323,6 @@ void OnCommand(Event event) {
} }
} }
if (CtrlPress(SDLK_F)) {
Window *window = GetWindow(SearchBarWindowID);
window->visible = !window->visible;
}
if (CtrlPress(SDLK_S)) {
SaveBuffer(active.buffer);
}
if (CtrlPress(SDLK_PERIOD)) {
String name = ChopLastSlash(main.buffer->name);
if (EndsWith(main.buffer->name, "dirlisting")) {
name = ChopLastSlash(name);
}
Open(name);
}
if (CtrlShiftPress(SDLK_L)) {
EncloseSpace(active.view);
} else if (CtrlPress(SDLK_L)) {
EncloseLine(active.view);
}
if (CtrlShiftPress(SDLK_G)) {
} else if (CtrlPress(SDLK_G)) {
}
if (AltPress(SDLK_Q)) {
GotoBackward(main.window);
}
if (CtrlPress(SDLK_Q)) {
if (active.view->fuzzy_search) {
FuzzySearchOpen(active);
} else {
Open(FetchLoadWord());
}
}
if (Press(SDLK_ESCAPE)) {
active.view->carets.len = 1;
active.view->carets[0] = MakeCaret(GetFront(active.view->carets[0]));
if (active.window->lose_focus_on_escape && active.window->id == ActiveWindowID) {
if (active.window->layout) {
//
} else {
NextActiveWindowID = LastActiveLayoutWindowID;
}
}
}
// :OnCommandEnding // :OnCommandEnding
MergeCarets(active.buffer, &active.view->carets); MergeCarets(active.buffer, &active.view->carets);
IF_DEBUG(AssertRanges(active.view->carets)); IF_DEBUG(AssertRanges(active.view->carets));

View File

@@ -86,3 +86,20 @@ void ClipboardPaste(View *view) {
} }
EndEdit(buffer, &edits, &view->carets, KILL_SELECTION); EndEdit(buffer, &edits, &view->carets, KILL_SELECTION);
} }
void Command_Paste(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
ClipboardPaste(active.view);
} RegisterCommand(Command_Paste, "ctrl-v");
void Command_Copy(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
ClipboardCopy(active.view);
} RegisterCommand(Command_Copy, "ctrl-c");
void Command_Cut(CommandContext *ctx) {
BSet active = GetBSet(ActiveWindowID);
SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets);
ClipboardCopy(active.view);
Replace(active.view, u"");
} RegisterCommand(Command_Cut, "ctrl-x");

View File

@@ -260,6 +260,91 @@ const char *SDLKeycodeToName(SDL_Keycode keycode) {
} }
} }
struct { String string; EventKind value; } MouseConversionTable[] = {
{"mousex1", EVENT_MOUSE_X1},
{"mousex2", EVENT_MOUSE_X2},
{"mouseleft", EVENT_MOUSE_LEFT},
{"mouseright", EVENT_MOUSE_RIGHT},
{"mousemiddle", EVENT_MOUSE_MIDDLE},
};
struct { String string; SDL_Keycode value; } SDLKeycodeConversionTable[] = {
{"enter", SDLK_RETURN},
{"escape", SDLK_ESCAPE},
{"backspace", SDLK_BACKSPACE},
{"tab", SDLK_TAB},
{"space", SDLK_SPACE},
{"minus", SDLK_MINUS},
{"period", SDLK_PERIOD},
{"slash", SDLK_SLASH},
{"0", SDLK_0},
{"1", SDLK_1},
{"2", SDLK_2},
{"3", SDLK_3},
{"4", SDLK_4},
{"5", SDLK_5},
{"6", SDLK_6},
{"7", SDLK_7},
{"8", SDLK_8},
{"9", SDLK_9},
{"semicolon", SDLK_SEMICOLON},
{"less", SDLK_LESS},
{"equals", SDLK_EQUALS},
{"greater", SDLK_GREATER},
{"leftbracket", SDLK_LEFTBRACKET},
{"backslash", SDLK_BACKSLASH},
{"rightbracket", SDLK_RIGHTBRACKET},
{"grave", SDLK_GRAVE},
{"a", SDLK_A},
{"b", SDLK_B},
{"c", SDLK_C},
{"d", SDLK_D},
{"e", SDLK_E},
{"f", SDLK_F},
{"g", SDLK_G},
{"h", SDLK_H},
{"i", SDLK_I},
{"j", SDLK_J},
{"k", SDLK_K},
{"l", SDLK_L},
{"m", SDLK_M},
{"n", SDLK_N},
{"o", SDLK_O},
{"p", SDLK_P},
{"q", SDLK_Q},
{"r", SDLK_R},
{"s", SDLK_S},
{"t", SDLK_T},
{"u", SDLK_U},
{"v", SDLK_V},
{"w", SDLK_W},
{"x", SDLK_X},
{"y", SDLK_Y},
{"z", SDLK_Z},
{"delete", SDLK_DELETE},
{"capslock", SDLK_CAPSLOCK},
{"f1", SDLK_F1},
{"f2", SDLK_F2},
{"f3", SDLK_F3},
{"f4", SDLK_F4},
{"f5", SDLK_F5},
{"f6", SDLK_F6},
{"f7", SDLK_F7},
{"f8", SDLK_F8},
{"f9", SDLK_F9},
{"f10", SDLK_F10},
{"f11", SDLK_F11},
{"f12", SDLK_F12},
{"insert", SDLK_INSERT},
{"home", SDLK_HOME},
{"pageup", SDLK_PAGEUP},
{"end", SDLK_END},
{"pagedown", SDLK_PAGEDOWN},
{"right", SDLK_RIGHT},
{"left", SDLK_LEFT},
{"down", SDLK_DOWN},
{"up", SDLK_UP},
};
void FillEventWithBasicData(Event *event) { void FillEventWithBasicData(Event *event) {
SDL_Keymod mod = SDL_GetModState(); SDL_Keymod mod = SDL_GetModState();
@@ -468,14 +553,6 @@ void Serialize(Serializer *s, Event *e) {
SerializeEnd(s); 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 Ctrl() event.ctrl
#define Alt() event.alt #define Alt() event.alt
#define Shift() event.shift #define Shift() event.shift

View File

@@ -31,7 +31,6 @@ ViewID SearchViewID;
BufferID SearchBufferID; BufferID SearchBufferID;
WindowID ActiveWindowID; WindowID ActiveWindowID;
WindowID NextActiveWindowID;
WindowID LastActiveLayoutWindowID; WindowID LastActiveLayoutWindowID;
WindowID ScrollbarSelected = {-1}; WindowID ScrollbarSelected = {-1};
WindowID DocumentSelected = {-1}; WindowID DocumentSelected = {-1};
@@ -50,11 +49,9 @@ View *TraceView;
String WorkDir; String WorkDir;
RandomSeed UniqueBufferNameSeed = {}; RandomSeed UniqueBufferNameSeed = {};
Array<Event> EventPlayback; Array<Event> EventPlayback;
lua_State *LuaState = NULL;
// lua BlockArena Perm;
lua_State *LuaState = NULL; Event *OnCommandEvent;
String16 LuaCommandResult = {};
extern luaL_Reg LuaFunctions[];
// clipboard // clipboard
BlockArena ClipboardArena; BlockArena ClipboardArena;
@@ -186,17 +183,40 @@ void ReloadStyle() {
StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout); StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout);
} }
typedef void CommandFunction(void); struct CommandContext {
Array<CommandFunction *> CommandFunctions; bool out_skip_rem_cmds;
};
#define STRINGIFY_(x) x typedef void Function(void *param);
#define STRINGIFY(x) STRINGIFY_(x) typedef void CommandFunction(CommandContext *ctx);
#define CONCAT_(a, b) a ## b typedef int LuaFunction(lua_State *state);
#define CONCAT(a, b) CONCAT_(a, b) struct FunctionData { String name; Function *function; };
struct LuaFunctionData { String name; LuaFunction *function; };
struct CommandData { String name; String binding; CommandFunction *function; struct Trigger *trigger; };
struct Register_Command { Array<CommandData> CommandFunctions;
Register_Command(CommandFunction *f) { Array<LuaFunctionData> LuaFunctions;
Add(&CommandFunctions, f); Array<FunctionData> TestFunctions;
struct Register_Function {
Register_Function(Array<FunctionData> *functions, String name, Function *f) {
int64_t pos = 0;
if (Seek(name, "_", &pos, 0)) {
name = Skip(name, pos + 1);
}
Add(functions, {name, f});
} }
}; };
#define RegisterCommand(NAME) Register_Command CONCAT(COMMAND, __COUNTER__)(NAME) #define RegisterFunction(functions, name) Register_Function RF__##name(functions, #name, name)
struct Register_Lua { Register_Lua(LuaFunction *function, String name) { if (StartsWith(name, "Lua_")) name = Skip(name, 4); Add(&LuaFunctions, {name, function}); } };
struct Register_Command { Register_Command(CommandFunction *function, String name, String binding) { if (StartsWith(name, "Command_")) name = Skip(name, 8); Add(&CommandFunctions, {name, binding, function}); } };
#define RegisterLua(NAME) Register_Lua RL_##NAME(NAME, #NAME)
#define RegisterCommand(name, binding) Register_Command RC__##name(name, #name, binding)
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;

View File

@@ -86,61 +86,6 @@ API String GetFieldString(lua_State *L, String name) {
return result; 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(); void ReloadStyle();
extern String BaseLuaConfig; extern String BaseLuaConfig;
@@ -206,9 +151,9 @@ API void InitLuaConfig() {
luaL_openlibs(LuaState); luaL_openlibs(LuaState);
lua_sethook(LuaState, HookLuaForceExit, LUA_MASKCOUNT, 100000000); lua_sethook(LuaState, HookLuaForceExit, LUA_MASKCOUNT, 100000000);
for (int i = 0; LuaFunctions[i].name; i += 1) { For(LuaFunctions) {
lua_pushcfunction(LuaState, LuaFunctions[i].func); lua_pushcfunction(LuaState, it.function);
lua_setglobal(LuaState, LuaFunctions[i].name); lua_setglobal(LuaState, it.name.data);
} }
#if OS_WINDOWS #if OS_WINDOWS
@@ -253,3 +198,97 @@ API void InitLuaConfig() {
ReloadLuaConfigs(true); ReloadLuaConfigs(true);
CallLuaOnInit(); 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);
}

View File

@@ -3,7 +3,6 @@ API Int GetStyleInt(String name, Int default_int);
API String GetStyleString(String name, String default_string); API String GetStyleString(String name, String default_string);
API Color GetColor(String name, Color default_color); API Color GetColor(String name, Color default_color);
API String GetFieldString(lua_State *L, String name); API String GetFieldString(lua_State *L, String name);
API int Lua_Play(lua_State *L);
API void LoadLuaBuffer(Buffer *lua_buffer); API void LoadLuaBuffer(Buffer *lua_buffer);
API void ReloadLuaConfigs(bool reload = false); API void ReloadLuaConfigs(bool reload = false);
API bool CallLuaFunc(char *func_name, int arg_count, int ret_count); API bool CallLuaFunc(char *func_name, int arg_count, int ret_count);

View File

@@ -9,7 +9,7 @@ int Lua_print(lua_State *L) {
Appendf(null_view, "\n"); Appendf(null_view, "\n");
lua_pop(L, nargs); lua_pop(L, nargs);
return 0; return 0;
} } RegisterLua(Lua_print);
int Lua_Print(lua_State *L) { int Lua_Print(lua_State *L) {
Scratch scratch; Scratch scratch;
@@ -21,7 +21,7 @@ int Lua_Print(lua_State *L) {
Appendf(TraceView, "\n"); Appendf(TraceView, "\n");
lua_pop(L, nargs); lua_pop(L, nargs);
return 0; return 0;
} } RegisterLua(Lua_Print);
int Lua_GetLoadWord(lua_State *L) { int Lua_GetLoadWord(lua_State *L) {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
@@ -34,7 +34,7 @@ int Lua_GetLoadWord(lua_State *L) {
String string = AllocCharString(scratch, active.buffer, range); String string = AllocCharString(scratch, active.buffer, range);
lua_pushlstring(L, string.data, string.len); lua_pushlstring(L, string.data, string.len);
return 1; return 1;
} } RegisterLua(Lua_GetLoadWord);
int Lua_BufferExists(lua_State *L) { int Lua_BufferExists(lua_State *L) {
String string = lua_tostring(L, 1); String string = lua_tostring(L, 1);
@@ -42,7 +42,7 @@ int Lua_BufferExists(lua_State *L) {
Buffer *buffer = GetBuffer(string); Buffer *buffer = GetBuffer(string);
lua_pushboolean(L, buffer != NULL); lua_pushboolean(L, buffer != NULL);
return 1; return 1;
} } RegisterLua(Lua_BufferExists);
int Lua_GetSelection(lua_State *L) { int Lua_GetSelection(lua_State *L) {
Scratch scratch; Scratch scratch;
@@ -51,7 +51,7 @@ int Lua_GetSelection(lua_State *L) {
String string = ToString(scratch, string16); String string = ToString(scratch, string16);
lua_pushlstring(L, string.data, string.len); lua_pushlstring(L, string.data, string.len);
return 1; return 1;
} } RegisterLua(Lua_GetSelection);
int Lua_GetEntireBuffer(lua_State *L) { int Lua_GetEntireBuffer(lua_State *L) {
Scratch scratch; Scratch scratch;
@@ -60,20 +60,20 @@ int Lua_GetEntireBuffer(lua_State *L) {
String string = ToString(scratch, string16); String string = ToString(scratch, string16);
lua_pushlstring(L, string.data, string.len); lua_pushlstring(L, string.data, string.len);
return 1; return 1;
} } RegisterLua(Lua_GetEntireBuffer);
int Lua_GetClipboard(lua_State *L) { int Lua_GetClipboard(lua_State *L) {
Scratch scratch; Scratch scratch;
String string = ToString(scratch, SavedClipboardString); String string = ToString(scratch, SavedClipboardString);
lua_pushlstring(L, string.data, string.len); lua_pushlstring(L, string.data, string.len);
return 1; return 1;
} } RegisterLua(Lua_GetClipboard);
int Lua_GetFilename(lua_State *L) { int Lua_GetFilename(lua_State *L) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
lua_pushlstring(L, main.buffer->name.data, main.buffer->name.len); lua_pushlstring(L, main.buffer->name.data, main.buffer->name.len);
return 1; return 1;
} } RegisterLua(Lua_GetFilename);
int Lua_GetLine(lua_State *L) { int Lua_GetLine(lua_State *L) {
BSet main = GetBSet(LastActiveLayoutWindowID); BSet main = GetBSet(LastActiveLayoutWindowID);
@@ -82,7 +82,7 @@ int Lua_GetLine(lua_State *L) {
Int line = PosToLine(main.buffer, front); Int line = PosToLine(main.buffer, front);
lua_pushinteger(L, line + 1); lua_pushinteger(L, line + 1);
return 1; return 1;
} } RegisterLua(Lua_GetLine);
int Lua_FileExists(lua_State *L) { int Lua_FileExists(lua_State *L) {
String path = luaL_checkstring(L, 1); String path = luaL_checkstring(L, 1);
@@ -90,103 +90,213 @@ int Lua_FileExists(lua_State *L) {
bool exists = FileExists(path); bool exists = FileExists(path);
lua_pushboolean(L, exists); lua_pushboolean(L, exists);
return 1; return 1;
} } RegisterLua(Lua_FileExists);
int Lua_GetWorkDir(lua_State *L) { int Lua_GetWorkDir(lua_State *L) {
lua_pushlstring(L, WorkDir.data, WorkDir.len); lua_pushlstring(L, WorkDir.data, WorkDir.len);
return 1; return 1;
} } RegisterLua(Lua_GetWorkDir);
int Lua_GetExeDir(lua_State *L) { int Lua_GetExeDir(lua_State *L) {
Scratch scratch; Scratch scratch;
String exe_dir = GetExeDir(scratch); String exe_dir = GetExeDir(scratch);
lua_pushlstring(L, exe_dir.data, exe_dir.len); lua_pushlstring(L, exe_dir.data, exe_dir.len);
return 1; return 1;
} } RegisterLua(Lua_GetExeDir);
int Lua_GetMainDir(lua_State *L) { int Lua_GetMainDir(lua_State *L) {
String name = GetMainDir(); String name = GetMainDir();
lua_pushlstring(L, name.data, name.len); lua_pushlstring(L, name.data, name.len);
return 1; return 1;
} } RegisterLua(Lua_GetMainDir);
struct OnOpenResult { int Lua_ListCommands(lua_State *L) {
String kind; BSet main = GetBSet(LastActiveLayoutWindowID);
String file_path; BeginJump(&main);
Int line, col; int i = 0;
String working_dir; For (LuaFunctions) {
String cmd; Appendf(main.view, "%20S() ", it.name);
}; if (((i + 1) % 6) == 0) {
Appendf(main.view, "\n");
}
i += 1;
}
EndJump(main);
ActiveWindowID = main.window->id;
return 0;
} RegisterLua(Lua_ListCommands);
OnOpenResult CallOnOpen(Allocator allocator, String path, String meta) { int Lua_GetBufferList(lua_State *L) {
lua_getglobal(LuaState, "OnOpen"); lua_createtable(L, 0, (int)Buffers.len);
lua_pushlstring(LuaState, path.data, path.len);
lua_pushlstring(LuaState, meta.data, meta.len); int i = 1;
if (!CallLuaFunc("OnOpen", 2, 1)) { For(Buffers) {
return {}; 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_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_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_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"); lua_getfield(L, -1, "cmd");
String line_string = GetFieldString(LuaState, "line"); if (!lua_isstring(L, -1)) luaL_error(L, "expected a string for cmd param");
String col_string = GetFieldString(LuaState, "col"); String cmd = lua_tostring(L, -1);
String cmd = GetFieldString(LuaState, "cmd"); lua_pop(L, 1);
String working_dir = GetFieldString(LuaState, "working_dir");
String kind = GetFieldString(LuaState, "kind");
OnOpenResult result = {}; lua_getfield(L, -1, "kind");
result.cmd = cmd; String kind = lua_tostring(L, -1);
result.working_dir = working_dir; lua_pop(L, 1);
result.file_path = file_path;
if (!IsAbsolute(result.file_path)) { BSet main = GetBSet(LastActiveLayoutWindowID);
String dir = GetMainDir(); if (kind == "console") {
result.file_path = Format(allocator, "%S/%S", dir, result.file_path); BSet set = GetConsoleSet();
} main.window->active_goto_list = set.view->id;
if (col_string.len) { main.window->goto_list_pos = set.buffer->len;
result.col = strtoll(col_string.data, NULL, 10); 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;
ActiveWindowID = main.window->id;
} else { } 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);
ActiveWindowID = 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; return result;
} }
bool CallIsCode(String path, String meta = "") { // :Event
lua_getglobal(LuaState, "IsCode"); int Lua_Play(lua_State *L) {
lua_pushlstring(LuaState, path.data, path.len); if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events");
lua_pushlstring(LuaState, meta.data, meta.len); defer { lua_pop(L, 1); };
if (!CallLuaFunc("IsCode", 2, 1)) {
return false; 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); return 0;
lua_pop(LuaState, 1); } RegisterLua(Lua_Play);
return result;
}
void CallOnSave(BufferID buffer_id) {
lua_getglobal(LuaState, "OnSave");
lua_pushinteger(LuaState, buffer_id.id);
CallLuaFunc("OnSave", 1, 0);
}
bool CallOnCommand(Event *event) { int Lua_TrimTrailingWhitespace(lua_State *L) {
lua_getglobal(LuaState, "OnCommand"); lua_Integer buffer_id = luaL_checkinteger(L, 1);
PushEvent(LuaState, event); int trim_lines_with_caret = lua_toboolean(L, 2);
CallLuaFunc("OnCommand", 1, 1); lua_pop(L, 2);
bool result = lua_toboolean(LuaState, -1); Buffer *buffer = GetBuffer({buffer_id});
lua_pop(LuaState, 1); TrimTrailingWhitespace(buffer, trim_lines_with_caret);
return result; return 0;
} } RegisterLua(Lua_TrimTrailingWhitespace);
void CallLuaOnUpdate(Event *event) {
lua_getglobal(LuaState, "OnUpdate");
PushEvent(LuaState, event);
CallLuaFunc("OnUpdate", 1, 0);
}

View File

@@ -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},
};

View File

@@ -38,9 +38,6 @@ String GetMainDir() {
void GarbageCollect() { void GarbageCollect() {
Allocator sys_allocator = GetSystemAllocator(); Allocator sys_allocator = GetSystemAllocator();
ActiveWindowID = NextActiveWindowID;
For (Windows) { For (Windows) {
if (it->sync_visibility_with_focus) { if (it->sync_visibility_with_focus) {
if (it->id == ActiveWindowID) { if (it->id == ActiveWindowID) {
@@ -51,8 +48,8 @@ void GarbageCollect() {
} }
} }
Window *window = GetWindow(ActiveWindowID);
if (ActiveWindowID.id != LastActiveLayoutWindowID.id) { if (ActiveWindowID.id != LastActiveLayoutWindowID.id) {
Window *window = GetWindow(ActiveWindowID);
if (window->layout) { if (window->layout) {
LastActiveLayoutWindowID = ActiveWindowID; LastActiveLayoutWindowID = ActiveWindowID;
} }

245
src/text_editor/parser.cpp Normal file
View File

@@ -0,0 +1,245 @@
struct Lexer {
Allocator allocator;
char *at;
char *start;
char *end;
char *name;
int line, column;
};
enum TriggerKind {
TriggerKind_Error,
TriggerKind_Key,
TriggerKind_Mouse,
TriggerKind_Binary,
};
struct Trigger {
TriggerKind kind;
Trigger *left;
Trigger *right;
SDL_Keycode key;
struct {
EventKind event_kind : 8;
U32 ctrl : 1;
U32 alt : 1;
U32 shift : 1;
};
};
void Advance(Lexer *lex) {
if (lex->at < lex->end) {
if (lex->at[0] == '\n') {
lex->line += 1;
lex->column = 0;
} else {
lex->column += 1;
}
lex->at += 1;
}
}
void Advance(Lexer *lex, int n) {
for (int i = 0; i < n; i += 1) Advance(lex);
}
char At(Lexer *lex) {
if (lex->at < lex->end) {
return lex->at[0];
}
return 0;
}
String AsString(Lexer *lex) {
String result = {lex->at, lex->end - lex->at};
return result;
}
void EatWhitespace(Lexer *lex) {
while (IsWhitespace(At(lex))) {
Advance(lex);
}
}
Trigger *TriggerBinary(Lexer *lex, Trigger *left, Trigger *right, int key) {
Trigger *result = AllocType(lex->allocator, Trigger);
result->kind = TriggerKind_Binary;
result->key = key;
result->left = left;
result->right = right;
return result;
}
Trigger *ParseKeyAtom(Lexer *lex) {
Trigger *result = AllocType(lex->allocator, Trigger);
result->kind = TriggerKind_Key;
EatWhitespace(lex);
for (;;) {
String lex_string = AsString(lex);
if (StartsWith(lex_string, "ctrl")) {
result->ctrl = true;
Advance(lex, 4);
} else if (StartsWith(lex_string, "shift")) {
result->shift = true;
Advance(lex, 5);
} else if (StartsWith(lex_string, "alt")) {
result->alt = true;
Advance(lex, 3);
} else if (IsAlphanumeric(At(lex))) {
char *start = lex->at;
while (IsAlphanumeric(At(lex))) {
Advance(lex);
}
String a = {start, lex->at - start};
Advance(lex);
bool found = false;
for (int i = 0; !found && i < Lengthof(MouseConversionTable); i += 1) {
if (a == MouseConversionTable[i].string) {
result->event_kind = MouseConversionTable[i].value;
result->kind = TriggerKind_Mouse;
found = true;
}
}
for (int i = 0; !found && i < Lengthof(SDLKeycodeConversionTable); i += 1) {
if (a == SDLKeycodeConversionTable[i].string) {
result->key = SDLKeycodeConversionTable[i].value;
found = true;
}
}
if (!found) {
result->kind = TriggerKind_Error;
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected identifier: '%d'", lex->name, lex->line, lex->column, result->key);
return result;
}
} else {
result->kind = TriggerKind_Error;
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected character: '%c'", lex->name, lex->line, lex->column, At(lex));
return result;
}
if (At(lex) == '-') {
Advance(lex);
} else {
break;
}
}
return result;
}
Trigger *ParseKeyChord(Lexer *lex) {
Trigger *left = ParseKeyAtom(lex);
EatWhitespace(lex);
while (IsAlphanumeric(At(lex))) {
int op = At(lex);
left = TriggerBinary(lex, left, ParseKeyChord(lex), ' ');
EatWhitespace(lex);
}
return left;
}
Trigger *ParseKeyExpr(Lexer *lex) {
Trigger *left = ParseKeyChord(lex);
EatWhitespace(lex);
while (At(lex) == '|') {
Advance(lex);
left = TriggerBinary(lex, left, ParseKeyExpr(lex), '|');
EatWhitespace(lex);
}
return left;
}
Trigger *ParseKey(Allocator allocator, String key, char *debug_name) {
Lexer lex = {allocator, key.data, key.data, key.data + key.len, debug_name};
Trigger *result = ParseKeyExpr(&lex);
return result;
}
bool MatchEvent(Trigger *trigger, Event *event) {
if (trigger->kind == TriggerKind_Key) {
if (trigger->key == event->key && trigger->ctrl == event->ctrl && trigger->alt == event->alt && trigger->shift == event->shift) {
return true;
}
} else if (trigger->kind == TriggerKind_Mouse) {
if (trigger->event_kind == event->kind) {
return true;
}
} else if (trigger->kind == TriggerKind_Binary) {
if (trigger->key == ' ') {
return false;
} else if (trigger->key == '|') {
bool ok = MatchEvent(trigger->left, event);
if (ok) return ok;
ok = MatchEvent(trigger->right, event);
if (ok) return ok;
} ElseInvalidCodepath();
} else {
return false;
}
return false;
}
void TestParser(void *param) {
Scratch scratch;
{
char *cmd = "ctrl-b";
Lexer base_lex = {scratch, cmd, cmd, cmd + strlen(cmd), "keybinding"};
Trigger *trigger = ParseKeyExpr(&base_lex);
Assert(trigger->kind == TriggerKind_Key);
Assert(trigger->key == SDLK_B);
Assert(trigger->ctrl);
Assert(trigger->shift == 0);
}
{
char *cmd = "ctrl-b shift-ctrl-a";
Lexer base_lex = {scratch, cmd, cmd, cmd + strlen(cmd), "keybinding"};
Trigger *trigger = ParseKeyExpr(&base_lex);
Assert(trigger->kind == TriggerKind_Binary);
Assert(trigger->key == ' ');
Assert(trigger->left->kind == TriggerKind_Key);
Assert(trigger->left->key == SDLK_B);
Assert(trigger->left->ctrl);
Assert(trigger->left->shift == 0);
Assert(trigger->right->kind == TriggerKind_Key);
Assert(trigger->right->key == SDLK_A);
Assert(trigger->right->ctrl);
Assert(trigger->right->shift);
}
{
char *cmd = "ctrl-b shift-ctrl-a | ctrl-c | ctrl-d";
Lexer base_lex = {scratch, cmd, cmd, cmd + strlen(cmd), "keybinding"};
Trigger *trigger = ParseKeyExpr(&base_lex);
Assert(trigger->kind == TriggerKind_Binary);
Assert(trigger->key == '|');
Assert(trigger->left->kind == TriggerKind_Binary);
Assert(trigger->left->key == ' ');
Assert(trigger->right->kind == TriggerKind_Binary);
Assert(trigger->right->key == '|');
Event event = {};
event.kind = EVENT_KEY_PRESS;
event.key = SDLK_D;
event.ctrl = 1;
bool ok = MatchEvent(trigger, &event);
Assert(ok);
event.key = SDLK_F1;
ok = MatchEvent(trigger, &event);
Assert(ok == 0);
event.ctrl = 1;
event.shift = 1;
event.key = SDLK_A;
ok = MatchEvent(trigger, &event);
Assert(!ok);
}
} RegisterFunction(&TestFunctions, TestParser);

View File

@@ -33,14 +33,14 @@
#include "management.cpp" #include "management.cpp"
#include "process.cpp" #include "process.cpp"
#include "event.cpp" #include "event.cpp"
#include "parser.cpp"
#include "lua_api.cpp"
#include "commands.cpp" #include "commands.cpp"
#include "lua_api.cpp"
#include "commands_clipboard.cpp" #include "commands_clipboard.cpp"
#include "commands_bindings.cpp" #include "commands_bindings.cpp"
#include "title_bar.cpp" #include "title_bar.cpp"
#include "lua_api_generated.cpp"
#include "generated_config.cpp" #include "generated_config.cpp"
#include "draw.cpp" #include "draw.cpp"
@@ -120,9 +120,6 @@ void SetMouseCursor(Event event) {
return; return;
} }
} }
SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT); SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT);
} }
@@ -138,7 +135,9 @@ void Update(Event event) {
view->update_scroll = true; view->update_scroll = true;
} }
OnCommandEvent = &event;
OnCommand(event); OnCommand(event);
OnCommandEvent = NULL;
UpdateProcesses(); UpdateProcesses();
CoUpdate(&event); CoUpdate(&event);
ReloadLuaConfigs(); ReloadLuaConfigs();
@@ -239,7 +238,6 @@ void MainLoop() {
SDL_GL_SwapWindow(SDLWindow); SDL_GL_SwapWindow(SDLWindow);
} }
#if _WIN32 #if _WIN32
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
#else #else
@@ -256,18 +254,21 @@ int main(int argc, char **argv)
if (1) { if (1) {
RunArenaTest(); RunArenaTest();
RunBufferTest(); For (TestFunctions) {
it.function(NULL);
}
// ReportErrorf("Testing DONE\n"); // ReportErrorf("Testing DONE\n");
// return 0; // return 0;
} }
#if !OS_WINDOWS #if !OS_WINDOWS
for (int i = 0; environ[i]; i += 1) { for (int i = 0; environ[i]; i += 1) {
Add(&Enviroment, Copy(GetSystemAllocator(), environ[i])); Add(&Enviroment, Copy(Perm, environ[i]));
} }
#endif #endif
WorkDir = GetWorkingDir(SysAllocator); WorkDir = GetWorkingDir(Perm);
{ {
String sdl_config_path = SDL_GetPrefPath("krzosa", "text_editor"); String sdl_config_path = SDL_GetPrefPath("krzosa", "text_editor");
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '\\') { if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '\\') {
@@ -276,7 +277,7 @@ int main(int argc, char **argv)
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '/') { if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '/') {
sdl_config_path = Chop(sdl_config_path, 1); // chop '/' sdl_config_path = Chop(sdl_config_path, 1); // chop '/'
} }
ConfigDir = NormalizePath(SysAllocator, sdl_config_path); ConfigDir = NormalizePath(Perm, sdl_config_path);
SDL_free(sdl_config_path.data); SDL_free(sdl_config_path.data);
} }
@@ -353,6 +354,11 @@ int main(int argc, char **argv)
InitWindows(); InitWindows();
InitOS(ReportWarningf); InitOS(ReportWarningf);
For (CommandFunctions) {
if (it.binding.len != 0) {
it.trigger = ParseKey(Perm, it.binding, it.name.data);
}
}
for (int i = 1; i < argc; i += 1) { for (int i = 1; i < argc; i += 1) {
String it = argv[i]; String it = argv[i];

View File

@@ -250,8 +250,8 @@ void LayoutWindows(int16_t wx, int16_t wy) {
Rect2 screen_rect = Rect0Size(wx, wy); Rect2 screen_rect = Rect0Size(wx, wy);
Vec2 size = GetSize(screen_rect); Vec2 size = GetSize(screen_rect);
Rect2 a = CutLeft(&screen_rect, 0.3f * size.x); Rect2 a = CutRight(&screen_rect, 0.3f * size.x);
Rect2 b = CutBottom(&a, 0.4f * size.y); Rect2 b = CutTop(&a, 0.4f * size.y);
Rect2 c = Shrink(b, 20); Rect2 c = Shrink(b, 20);
n->document_rect = n->total_rect = ToRect2I(c); n->document_rect = n->total_rect = ToRect2I(c);
} }
@@ -280,3 +280,40 @@ void LayoutWindows(int16_t wx, int16_t wy) {
i += 1; 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;
}

View File

@@ -34,6 +34,7 @@ struct Window {
bool sync_visibility_with_focus : 1; bool sync_visibility_with_focus : 1;
bool lose_focus_on_escape : 1; bool lose_focus_on_escape : 1;
bool jump_history : 1; bool jump_history : 1;
bool eval_command : 1;
}; };
}; };