Binding parser, TestFunctions

This commit is contained in:
Krzosa Karol
2025-12-15 23:29:18 +01:00
parent 4e5a0f6a9b
commit 5e7acd4a20
11 changed files with 452 additions and 124 deletions

View File

@@ -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.

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

@@ -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

@@ -1400,7 +1400,7 @@ void RunBufferTest() {
DeinitBuffer(&buffer); DeinitBuffer(&buffer);
TrackingAllocatorCheck(); TrackingAllocatorCheck();
} }
} } RegisterFunction(&TestFunctions, RunBufferTest);
/////////////////////////////// ///////////////////////////////
// Management // Management

View File

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

View File

@@ -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();
} }

View File

@@ -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();

View File

@@ -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)

View File

@@ -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
View 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);

View File

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