Binding parser, TestFunctions
This commit is contained in:
@@ -37,9 +37,29 @@ Commands TODO:
|
|||||||
- 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?
|
- I'M SETTING ACTIVE WINDOW AFTER COMMAND!!! DO WE CONTINUE WITH THIS?
|
||||||
- RegisterCommand(Command_ShowCommands, KEY_P | KEY_CTRL)
|
|
||||||
|
## Hooks and bindings
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
struct Hook {
|
||||||
|
String name;
|
||||||
|
String trigger;
|
||||||
|
HookFunction function;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Command_New() {
|
||||||
|
...
|
||||||
|
} RegisterCommand(Command_New, "ctrl-n");
|
||||||
|
|
||||||
|
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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -1400,7 +1400,7 @@ void RunBufferTest() {
|
|||||||
DeinitBuffer(&buffer);
|
DeinitBuffer(&buffer);
|
||||||
TrackingAllocatorCheck();
|
TrackingAllocatorCheck();
|
||||||
}
|
}
|
||||||
}
|
} RegisterFunction(&TestFunctions, RunBufferTest);
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Management
|
// Management
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -677,19 +668,6 @@ void SaveBuffer(Buffer *buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command_Save() {
|
|
||||||
BSet active = GetBSet(LastActiveLayoutWindowID);
|
|
||||||
SaveBuffer(active.buffer);
|
|
||||||
} RegisterCommand(Command_Save);
|
|
||||||
|
|
||||||
void Command_SaveAll() {
|
|
||||||
For(Buffers) {
|
|
||||||
if (it->file_mod_time) {
|
|
||||||
SaveBuffer(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} RegisterCommand(Command_SaveAll);
|
|
||||||
|
|
||||||
void KillSelectedLines(View *view) {
|
void KillSelectedLines(View *view) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
@@ -953,12 +931,6 @@ void ReopenBuffer(Buffer *buffer) {
|
|||||||
buffer->dirty = false;
|
buffer->dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command_Reopen() {
|
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
|
||||||
ReopenBuffer(main.buffer);
|
|
||||||
ActiveWindowID = main.window->id;
|
|
||||||
} RegisterCommand(Command_Reopen);
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -976,11 +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);
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -1000,23 +967,6 @@ void NewDir(Window *window, String name = "") {
|
|||||||
Open(name);
|
Open(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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)) {
|
||||||
@@ -1035,15 +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);
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -1117,6 +1058,84 @@ BSet Open(String16 path, String meta) {
|
|||||||
return Open(string, meta);
|
return Open(string, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Eval(String string) {
|
||||||
|
if (luaL_dostring(LuaState, string.data) != LUA_OK) {
|
||||||
|
const char *error_message = lua_tostring(LuaState, -1);
|
||||||
|
ReportWarningf("Execution error! %s", error_message);
|
||||||
|
lua_pop(LuaState, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Eval(String16 string) {
|
||||||
|
Scratch scratch;
|
||||||
|
Eval(ToString(scratch, string));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetProjectFile(Buffer *buffer) {
|
||||||
|
WorkDir = ChopLastSlash(buffer->name);
|
||||||
|
LuaProjectBuffer = buffer;
|
||||||
|
LuaProjectBuffer->user_change_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_Save() {
|
||||||
|
BSet active = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
SaveBuffer(active.buffer);
|
||||||
|
} RegisterCommand(Command_Save);
|
||||||
|
|
||||||
|
void Command_SaveAll() {
|
||||||
|
For(Buffers) {
|
||||||
|
if (it->file_mod_time) {
|
||||||
|
SaveBuffer(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} RegisterCommand(Command_SaveAll);
|
||||||
|
|
||||||
|
void Command_Reopen() {
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
ReopenBuffer(main.buffer);
|
||||||
|
ActiveWindowID = main.window->id;
|
||||||
|
} RegisterCommand(Command_Reopen);
|
||||||
|
|
||||||
|
void Command_New() {
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
New(main.window, "");
|
||||||
|
} RegisterCommand(Command_New);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
void Command_ShowBufferList() {
|
void Command_ShowBufferList() {
|
||||||
BSet command_bar = GetBSet(CommandBarWindowID);
|
BSet command_bar = GetBSet(CommandBarWindowID);
|
||||||
command_bar.window->visible = true;
|
command_bar.window->visible = true;
|
||||||
@@ -1158,25 +1177,6 @@ void Command_ListViews() {
|
|||||||
SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer));
|
SelectRange(command_bar.view, GetBufferEndAsRange(command_bar.buffer));
|
||||||
} RegisterCommand(Command_ListViews);
|
} RegisterCommand(Command_ListViews);
|
||||||
|
|
||||||
void Eval(String string) {
|
|
||||||
if (luaL_dostring(LuaState, string.data) != LUA_OK) {
|
|
||||||
const char *error_message = lua_tostring(LuaState, -1);
|
|
||||||
ReportWarningf("Execution error! %s", error_message);
|
|
||||||
lua_pop(LuaState, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eval(String16 string) {
|
|
||||||
Scratch scratch;
|
|
||||||
Eval(ToString(scratch, string));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetProjectFile(Buffer *buffer) {
|
|
||||||
WorkDir = ChopLastSlash(buffer->name);
|
|
||||||
LuaProjectBuffer = buffer;
|
|
||||||
LuaProjectBuffer->user_change_id = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Command_SetProjectFile() {
|
void Command_SetProjectFile() {
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
SetProjectFile(main.buffer);
|
SetProjectFile(main.buffer);
|
||||||
@@ -1197,15 +1197,6 @@ void Command_SetProject() {
|
|||||||
Command_SetProjectFile();
|
Command_SetProjectFile();
|
||||||
} RegisterCommand(Command_SetProject);
|
} RegisterCommand(Command_SetProject);
|
||||||
|
|
||||||
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() {
|
void Command_ToggleDebug() {
|
||||||
Window *window = GetWindow(DebugWindowID);
|
Window *window = GetWindow(DebugWindowID);
|
||||||
window->visible = !window->visible;
|
window->visible = !window->visible;
|
||||||
|
|||||||
@@ -200,15 +200,6 @@ void OnCommand(Event event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)) {
|
||||||
@@ -313,6 +304,15 @@ void OnCommand(Event event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Mouse(X2)) {
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
GotoForward(main.window);
|
||||||
|
}
|
||||||
|
if (Mouse(X1)) {
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
GotoBackward(main.window);
|
||||||
|
}
|
||||||
|
|
||||||
if (CtrlPress(SDLK_W)) {
|
if (CtrlPress(SDLK_W)) {
|
||||||
Command_KillWindow();
|
Command_KillWindow();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,6 +260,87 @@ const char *SDLKeycodeToName(SDL_Keycode keycode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_Keycode NameToSDLKeycode(String name) {
|
||||||
|
if (name == "enter") return SDLK_RETURN;
|
||||||
|
if (name == "escape") return SDLK_ESCAPE;
|
||||||
|
if (name == "backspace") return SDLK_BACKSPACE;
|
||||||
|
if (name == "tab") return SDLK_TAB;
|
||||||
|
if (name == "space") return SDLK_SPACE;
|
||||||
|
if (name == "-") return SDLK_MINUS;
|
||||||
|
if (name == ".") return SDLK_PERIOD;
|
||||||
|
if (name == "/") return SDLK_SLASH;
|
||||||
|
if (name == "0") return SDLK_0;
|
||||||
|
if (name == "1") return SDLK_1;
|
||||||
|
if (name == "2") return SDLK_2;
|
||||||
|
if (name == "3") return SDLK_3;
|
||||||
|
if (name == "4") return SDLK_4;
|
||||||
|
if (name == "5") return SDLK_5;
|
||||||
|
if (name == "6") return SDLK_6;
|
||||||
|
if (name == "7") return SDLK_7;
|
||||||
|
if (name == "8") return SDLK_8;
|
||||||
|
if (name == "9") return SDLK_9;
|
||||||
|
if (name == ":") return SDLK_COLON;
|
||||||
|
if (name == ";") return SDLK_SEMICOLON;
|
||||||
|
if (name == "<") return SDLK_LESS;
|
||||||
|
if (name == "=") return SDLK_EQUALS;
|
||||||
|
if (name == ">") return SDLK_GREATER;
|
||||||
|
if (name == "?") return SDLK_QUESTION;
|
||||||
|
if (name == "[") return SDLK_LEFTBRACKET;
|
||||||
|
if (name == "\\") return SDLK_BACKSLASH;
|
||||||
|
if (name == "]") return SDLK_RIGHTBRACKET;
|
||||||
|
if (name == "`") return SDLK_GRAVE;
|
||||||
|
if (name == "a") return SDLK_A;
|
||||||
|
if (name == "b") return SDLK_B;
|
||||||
|
if (name == "c") return SDLK_C;
|
||||||
|
if (name == "d") return SDLK_D;
|
||||||
|
if (name == "e") return SDLK_E;
|
||||||
|
if (name == "f") return SDLK_F;
|
||||||
|
if (name == "g") return SDLK_G;
|
||||||
|
if (name == "h") return SDLK_H;
|
||||||
|
if (name == "i") return SDLK_I;
|
||||||
|
if (name == "j") return SDLK_J;
|
||||||
|
if (name == "k") return SDLK_K;
|
||||||
|
if (name == "l") return SDLK_L;
|
||||||
|
if (name == "m") return SDLK_M;
|
||||||
|
if (name == "n") return SDLK_N;
|
||||||
|
if (name == "o") return SDLK_O;
|
||||||
|
if (name == "p") return SDLK_P;
|
||||||
|
if (name == "q") return SDLK_Q;
|
||||||
|
if (name == "r") return SDLK_R;
|
||||||
|
if (name == "s") return SDLK_S;
|
||||||
|
if (name == "t") return SDLK_T;
|
||||||
|
if (name == "u") return SDLK_U;
|
||||||
|
if (name == "v") return SDLK_V;
|
||||||
|
if (name == "w") return SDLK_W;
|
||||||
|
if (name == "x") return SDLK_X;
|
||||||
|
if (name == "y") return SDLK_Y;
|
||||||
|
if (name == "z") return SDLK_Z;
|
||||||
|
if (name == "delete") return SDLK_DELETE;
|
||||||
|
if (name == "capslock") return SDLK_CAPSLOCK;
|
||||||
|
if (name == "f1") return SDLK_F1;
|
||||||
|
if (name == "f2") return SDLK_F2;
|
||||||
|
if (name == "f3") return SDLK_F3;
|
||||||
|
if (name == "f4") return SDLK_F4;
|
||||||
|
if (name == "f5") return SDLK_F5;
|
||||||
|
if (name == "f6") return SDLK_F6;
|
||||||
|
if (name == "f7") return SDLK_F7;
|
||||||
|
if (name == "f8") return SDLK_F8;
|
||||||
|
if (name == "f9") return SDLK_F9;
|
||||||
|
if (name == "f10") return SDLK_F10;
|
||||||
|
if (name == "f11") return SDLK_F11;
|
||||||
|
if (name == "f12") return SDLK_F12;
|
||||||
|
if (name == "insert") return SDLK_INSERT;
|
||||||
|
if (name == "home") return SDLK_HOME;
|
||||||
|
if (name == "pageup") return SDLK_PAGEUP;
|
||||||
|
if (name == "end") return SDLK_END;
|
||||||
|
if (name == "pagedown") return SDLK_PAGEDOWN;
|
||||||
|
if (name == "right") return SDLK_RIGHT;
|
||||||
|
if (name == "left") return SDLK_LEFT;
|
||||||
|
if (name == "down") return SDLK_DOWN;
|
||||||
|
if (name == "up") return SDLK_UP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FillEventWithBasicData(Event *event) {
|
void FillEventWithBasicData(Event *event) {
|
||||||
SDL_Keymod mod = SDL_GetModState();
|
SDL_Keymod mod = SDL_GetModState();
|
||||||
|
|||||||
@@ -181,18 +181,26 @@ void ReloadStyle() {
|
|||||||
StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout);
|
StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void CommandFunction(void);
|
typedef void Function(void);
|
||||||
struct CommandFunctionMeta {
|
|
||||||
String name;
|
|
||||||
CommandFunction *function;
|
|
||||||
};
|
|
||||||
Array<CommandFunctionMeta> 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);
|
typedef int LuaFunction(lua_State *state);
|
||||||
struct LuaFunctionMeta { String name; LuaFunction *function; };
|
struct FunctionData { String name; Function *function; };
|
||||||
Array<LuaFunctionMeta> LuaFunctions;
|
struct LuaFunctionData { String name; LuaFunction *function; };
|
||||||
|
|
||||||
|
Array<FunctionData> CommandFunctions;
|
||||||
|
Array<LuaFunctionData> LuaFunctions;
|
||||||
|
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 RegisterFunction(functions, name) Register_Function RF__##name(functions, #name, name)
|
||||||
|
#define RegisterCommand(name) RegisterFunction(&CommandFunctions, name)
|
||||||
struct Register_Lua { Register_Lua(LuaFunction *function, String name) { if (StartsWith(name, "Lua_")) name = Skip(name, 4); Add(&LuaFunctions, {name, function}); } };
|
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)
|
#define RegisterLua(NAME) Register_Lua CONCAT(COMMAND, __COUNTER__)(NAME, #NAME)
|
||||||
|
|
||||||
|
|||||||
@@ -341,3 +341,12 @@ int Lua_Play(lua_State *L) {
|
|||||||
return 0;
|
return 0;
|
||||||
} RegisterLua(Lua_Play);
|
} RegisterLua(Lua_Play);
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
} RegisterLua(Lua_TrimTrailingWhitespace);
|
||||||
|
|||||||
221
src/text_editor/parser.cpp
Normal file
221
src/text_editor/parser.cpp
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
struct Lexer {
|
||||||
|
Allocator allocator;
|
||||||
|
char *at;
|
||||||
|
char *start;
|
||||||
|
char *end;
|
||||||
|
char *name;
|
||||||
|
int line, column;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TriggerKind {
|
||||||
|
TriggerKind_Error,
|
||||||
|
TriggerKind_Key,
|
||||||
|
TriggerKind_Binary,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Trigger {
|
||||||
|
TriggerKind kind;
|
||||||
|
Trigger *left;
|
||||||
|
Trigger *right;
|
||||||
|
SDL_Keycode key;
|
||||||
|
struct {
|
||||||
|
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};
|
||||||
|
result->key = NameToSDLKeycode(a);
|
||||||
|
if (result->key == 0) {
|
||||||
|
result->kind = TriggerKind_Error;
|
||||||
|
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected identifier: '%S'", lex->name, lex->line, lex->column, result->key);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
Advance(lex);
|
||||||
|
} 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 *ParseKeyOr(Lexer *lex) {
|
||||||
|
Trigger *left = ParseKeyChord(lex);
|
||||||
|
EatWhitespace(lex);
|
||||||
|
while (At(lex) == '|') {
|
||||||
|
Advance(lex);
|
||||||
|
left = TriggerBinary(lex, left, ParseKeyOr(lex), '|');
|
||||||
|
EatWhitespace(lex);
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchEvent(Trigger *trigger, Event *event) {
|
||||||
|
if (event->kind != EVENT_KEY_PRESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_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() {
|
||||||
|
Scratch scratch;
|
||||||
|
{
|
||||||
|
char *cmd = "ctrl-b";
|
||||||
|
Lexer base_lex = {scratch, cmd, cmd, cmd + strlen(cmd), "keybinding"};
|
||||||
|
Trigger *trigger = ParseKeyOr(&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 = ParseKeyOr(&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 = ParseKeyOr(&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);
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "management.cpp"
|
#include "management.cpp"
|
||||||
#include "process.cpp"
|
#include "process.cpp"
|
||||||
#include "event.cpp"
|
#include "event.cpp"
|
||||||
|
#include "parser.cpp"
|
||||||
|
|
||||||
#include "commands.cpp"
|
#include "commands.cpp"
|
||||||
#include "lua_api.cpp"
|
#include "lua_api.cpp"
|
||||||
@@ -119,9 +120,6 @@ void SetMouseCursor(Event event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT);
|
SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +236,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
|
||||||
@@ -255,7 +252,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (1) {
|
if (1) {
|
||||||
RunArenaTest();
|
RunArenaTest();
|
||||||
RunBufferTest();
|
For (TestFunctions) {
|
||||||
|
it.function();
|
||||||
|
}
|
||||||
|
|
||||||
// ReportErrorf("Testing DONE\n");
|
// ReportErrorf("Testing DONE\n");
|
||||||
// return 0;
|
// return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user