diff --git a/src/code.c b/src/code.c index d553ede..441ec12 100644 --- a/src/code.c +++ b/src/code.c @@ -865,37 +865,7 @@ static int funcCompare(const void* a, const void* b) if(item1->pos == NULL) return 1; if(item2->pos == NULL) return -1; - return strcmp(item1->name, item2->name); -} - -static char* getFuncName(const char* start, char* buffer) -{ - const char* ptr = start; - while(*ptr) - { - char sym = *ptr; - - if(isalpha_(sym) || isdigit(sym) || sym == ':'){} - else if(sym == '(') break; - else return NULL; - - ptr++; - } - - if(ptr) - { - size_t len = ptr - start; - - if(len < STUDIO_TEXT_BUFFER_WIDTH) - { - memcpy(buffer, start, len); - buffer[len] = '\0'; - - return buffer; - } - } - - return NULL; + return SDL_strcasecmp(item1->name, item2->name); } static void normalizeScroll(Code* code) @@ -938,118 +908,56 @@ static void updateOutlineCode(Code* code) updateEditor(code); } -static void setMoonscriptOutlineMode(Code* code) +static void initOutlineMode(Code* code) { OutlineItem* out = code->outline.items; OutlineItem* end = out + OUTLINE_SIZE; - char* ptr = code->src; - static const char FuncString[] = "=->"; + tic_mem* tic = code->tic; - char buffer[STUDIO_TEXT_BUFFER_WIDTH]; - char filter[STUDIO_TEXT_BUFFER_WIDTH]; - strcpy(filter, code->popup.text); + char buffer[STUDIO_TEXT_BUFFER_WIDTH] = {0}; + char filter[STUDIO_TEXT_BUFFER_WIDTH] = {0}; + SDL_strlcpy(filter, code->popup.text, sizeof(filter)); SDL_strlwr(filter); - while(ptr) + const tic_script_config* config = tic->api.get_script_config(tic); + + if(config->getOutline) { - ptr = strstr(ptr, FuncString); + s32 size = 0; + const tic_outline_item* items = config->getOutline(code->src, &size); - if(ptr && ptr > code->src) + for(s32 i = 0; i < size; i++) { - char* endPtr = ptr; - ptr += sizeof FuncString - 1; + const tic_outline_item* item = items + i; - while(endPtr >= code->src && !isalpha_(*endPtr) && !isdigit(*endPtr)) endPtr--; - - char* start = endPtr; - - for (const char* val = start-1; val >= code->src && (isalpha_(*val) || isdigit(*val)); val--, start--); - - if(start >= code->src) + if(out < end) { - memset(buffer, 0, sizeof buffer); - memcpy(buffer, start, endPtr - start + 1); - - strcpy(out->name, buffer); + out->pos = code->src + item->pos; + memset(out->name, 0, STUDIO_TEXT_BUFFER_WIDTH); + memcpy(out->name, out->pos, SDL_min(item->size, STUDIO_TEXT_BUFFER_WIDTH-1)); if(*filter) { + SDL_strlcpy(buffer, out->name, sizeof(buffer)); SDL_strlwr(buffer); - if(strstr(buffer, filter)) - { - out->pos = start; - out++; - } - } - else - { - out->pos = start; - out++; + + if(strstr(buffer, filter)) out++; + else out->pos = NULL; } + else out++; } + else break; } - else break; - - if(out >= end) break; } } -static void setLuaOutlineMode(Code* code) -{ - OutlineItem* out = code->outline.items; - OutlineItem* end = out + OUTLINE_SIZE; - - char* ptr = code->src; - static const char FuncString[] = "function "; - - char buffer[STUDIO_TEXT_BUFFER_WIDTH]; - char filter[STUDIO_TEXT_BUFFER_WIDTH]; - strcpy(filter, code->popup.text); - SDL_strlwr(filter); - - while(ptr) - { - ptr = strstr(ptr, FuncString); - - if(ptr) - { - ptr += sizeof FuncString - 1; - - if(getFuncName(ptr, buffer)) - { - strcpy(out->name, buffer); - - if(*filter) - { - SDL_strlwr(buffer); - if(strstr(buffer, filter)) - { - out->pos = ptr; - out++; - } - } - else - { - out->pos = ptr; - out++; - } - } - } - - if(out >= end) break; - } - -} - static void setOutlineMode(Code* code) { code->outline.index = 0; memset(code->outline.items, 0, OUTLINE_ITEMS_SIZE); - code->tic->api.get_script_config(code->tic)->lang == tic_script_moon - ? setMoonscriptOutlineMode(code) - : setLuaOutlineMode(code); + initOutlineMode(code); qsort(code->outline.items, OUTLINE_SIZE, sizeof(OutlineItem), funcCompare); updateOutlineCode(code); diff --git a/src/console.c b/src/console.c index 1f0d090..a331f0c 100644 --- a/src/console.c +++ b/src/console.c @@ -40,6 +40,13 @@ #define CONSOLE_BUFFER_SCREENS 64 #define CONSOLE_BUFFER_SIZE (CONSOLE_BUFFER_WIDTH * CONSOLE_BUFFER_HEIGHT * CONSOLE_BUFFER_SCREENS) +typedef enum +{ + LuaScript, + MoonScript, + JavaScript, +} ScriptLang; + #if defined(__WINDOWS__) || defined(__LINUX__) || defined(__MACOSX__) #define CAN_EXPORT 1 #endif @@ -381,20 +388,20 @@ static bool onConsoleLoadSectionCommand(Console* console, const char* param) return result; } -static void* getDemoCart(Console* console, tic_script_lang script, s32* size) +static void* getDemoCart(Console* console, ScriptLang script, s32* size) { char path[FILENAME_MAX] = {0}; { switch(script) { - case tic_script_lua: + case LuaScript: strcpy(path, DefaultLuaTicPath); break; - case tic_script_moon: + case MoonScript: strcpy(path, DefaultMoonTicPath); break; - case tic_script_js: + case JavaScript: strcpy(path, DefaultJSTicPath); break; } @@ -425,15 +432,15 @@ static void* getDemoCart(Console* console, tic_script_lang script, s32* size) switch(script) { - case tic_script_lua: + case LuaScript: demo = LuaDemoRom; romSize = sizeof LuaDemoRom; break; - case tic_script_moon: + case MoonScript: demo = MoonDemoRom; romSize = sizeof MoonDemoRom; break; - case tic_script_js: + case JavaScript: demo = JsDemoRom; romSize = sizeof JsDemoRom; break; @@ -464,11 +471,11 @@ static void onConsoleLoadDemoCommandConfirmed(Console* console, const char* para console->showGameMenu = false; if(strcmp(param, DefaultLuaTicPath) == 0) - data = getDemoCart(console, tic_script_lua, &size); + data = getDemoCart(console, LuaScript, &size); else if(strcmp(param, DefaultMoonTicPath) == 0) - data = getDemoCart(console, tic_script_moon, &size); + data = getDemoCart(console, MoonScript, &size); else if(strcmp(param, DefaultJSTicPath) == 0) - data = getDemoCart(console, tic_script_js, &size); + data = getDemoCart(console, JavaScript, &size); const char* name = getCartName(param); @@ -1012,7 +1019,7 @@ static void onConsoleLoadCommand(Console* console, const char* param) } } -static void loadDemo(Console* console, tic_script_lang script) +static void loadDemo(Console* console, ScriptLang script) { s32 size = 0; u8* data = getDemoCart(console, script, &size); @@ -1034,11 +1041,11 @@ static void onConsoleNewCommandConfirmed(Console* console, const char* param) if(param && strlen(param)) { if(strcmp(param, "lua") == 0) - loadDemo(console, tic_script_lua); + loadDemo(console, LuaScript); else if(strcmp(param, "moon") == 0 || strcmp(param, "moonscript") == 0) - loadDemo(console, tic_script_moon); + loadDemo(console, MoonScript); else if(strcmp(param, "js") == 0 || strcmp(param, "javascript") == 0) - loadDemo(console, tic_script_js); + loadDemo(console, JavaScript); else { printError(console, "\nunknown parameter: "); @@ -1047,7 +1054,7 @@ static void onConsoleNewCommandConfirmed(Console* console, const char* param) return; } } - else loadDemo(console, tic_script_lua); + else loadDemo(console, LuaScript); printBack(console, "\nnew cart is created"); commandDone(console); @@ -2661,7 +2668,7 @@ static void tick(Console* console) { if(!console->embed.yes) { - loadDemo(console, tic_script_lua); + loadDemo(console, LuaScript); printBack(console, "\n hello! type "); printFront(console, "help"); diff --git a/src/jsapi.c b/src/jsapi.c index 9dc802c..837ce2f 100644 --- a/src/jsapi.c +++ b/src/jsapi.c @@ -23,6 +23,8 @@ #include "machine.h" #include "tools.h" +#include + #include "ext/duktape/duktape.h" static const char TicMachine[] = "_TIC80"; @@ -886,16 +888,78 @@ static const char* const JsKeywords [] = "default", "if", "throw", "delete", "in", "try", "const" }; +static inline bool isalnum_(char c) {return isalnum(c) || c == '_';} + +static const tic_outline_item* getJsOutline(const char* code, s32* size) +{ + enum{Size = sizeof(tic_outline_item)}; + + *size = 0; + + static tic_outline_item* items = NULL; + + if(items) + { + free(items); + items = NULL; + } + + const char* ptr = code; + + while(true) + { + static const char FuncString[] = "function "; + + ptr = strstr(ptr, FuncString); + + if(ptr) + { + ptr += sizeof FuncString - 1; + + const char* start = ptr; + const char* end = start; + + while(*ptr) + { + char c = *ptr; + + if(isalnum_(c)); + else if(c == '(') + { + end = ptr; + break; + } + else break; + + ptr++; + } + + if(end > start) + { + items = items ? realloc(items, (*size + 1) * Size) : malloc(Size); + + items[*size].pos = start - code; + items[*size].size = end - start; + + (*size)++; + } + } + else break; + } + + return items; +} + static const tic_script_config JsSyntaxConfig = { - .lang = tic_script_js, - .init = initJavascript, .close = closeJavascript, .tick = callJavascriptTick, .scanline = callJavascriptScanline, .overlap = callJavascriptOverlap, + .getOutline = getJsOutline, + .blockCommentStart = "/*", .blockCommentEnd = "*/", .blockStringStart = NULL, diff --git a/src/luaapi.c b/src/luaapi.c index 97b0148..0402a3d 100644 --- a/src/luaapi.c +++ b/src/luaapi.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "machine.h" #include "ext/moonscript.h" @@ -1314,16 +1315,78 @@ static const char* const LuaKeywords [] = "return", "then", "true", "until", "while" }; +static inline bool isalnum_(char c) {return isalnum(c) || c == '_';} + +static const tic_outline_item* getLuaOutline(const char* code, s32* size) +{ + enum{Size = sizeof(tic_outline_item)}; + + *size = 0; + + static tic_outline_item* items = NULL; + + if(items) + { + free(items); + items = NULL; + } + + const char* ptr = code; + + while(true) + { + static const char FuncString[] = "function "; + + ptr = strstr(ptr, FuncString); + + if(ptr) + { + ptr += sizeof FuncString - 1; + + const char* start = ptr; + const char* end = start; + + while(*ptr) + { + char c = *ptr; + + if(isalnum_(c) || c == ':'); + else if(c == '(') + { + end = ptr; + break; + } + else break; + + ptr++; + } + + if(end > start) + { + items = items ? realloc(items, (*size + 1) * Size) : malloc(Size); + + items[*size].pos = start - code; + items[*size].size = end - start; + + (*size)++; + } + } + else break; + } + + return items; +} + static const tic_script_config LuaSyntaxConfig = { - .lang = tic_script_lua, - .init = initLua, .close = closeLua, .tick = callLuaTick, .scanline = callLuaScanline, .overlap = callLuaOverlap, + .getOutline = getLuaOutline, + .blockCommentStart = "--[[", .blockCommentEnd = "]]", .singleComment = "--", @@ -1353,16 +1416,66 @@ static const char* const MoonKeywords [] = "from", "class", "extends", "new" }; +static const tic_outline_item* getMoonOutline(const char* code, s32* size) +{ + enum{Size = sizeof(tic_outline_item)}; + + *size = 0; + + static tic_outline_item* items = NULL; + + if(items) + { + free(items); + items = NULL; + } + + const char* ptr = code; + + while(true) + { + static const char FuncString[] = "=->"; + + ptr = strstr(ptr, FuncString); + + if(ptr) + { + const char* end = ptr; + + ptr += sizeof FuncString - 1; + + while(end >= code && !isalnum_(*end)) end--; + + const char* start = end; + + for (const char* val = start-1; val >= code && (isalnum_(*val)); val--, start--); + + if(end > start) + { + items = items ? realloc(items, (*size + 1) * Size) : malloc(Size); + + items[*size].pos = start - code; + items[*size].size = end - start + 1; + + (*size)++; + } + } + else break; + } + + return items; +} + static const tic_script_config MoonSyntaxConfig = { - .lang = tic_script_moon, - .init = initMoonscript, .close = closeLua, .tick = callLuaTick, .scanline = callLuaScanline, .overlap = callLuaOverlap, + .getOutline = getMoonOutline, + .blockCommentStart = NULL, .blockCommentEnd = NULL, .blockStringStart = NULL, diff --git a/src/tic.h b/src/tic.h index 6cdd327..754b8d0 100644 --- a/src/tic.h +++ b/src/tic.h @@ -430,10 +430,3 @@ typedef enum tic_gamepad_input, tic_mouse_input, } tic_input_method; - -typedef enum -{ - tic_script_lua, - tic_script_moon, - tic_script_js, -} tic_script_lang; diff --git a/src/ticapi.h b/src/ticapi.h index db5be10..e88467d 100644 --- a/src/ticapi.h +++ b/src/ticapi.h @@ -70,8 +70,12 @@ typedef void(*tic_overlap)(tic_mem* memory, void* data); typedef struct { - tic_script_lang lang; + s32 pos; + s32 size; +} tic_outline_item; +typedef struct +{ struct { bool(*init)(tic_mem* memory, const char* code); @@ -82,6 +86,8 @@ typedef struct tic_overlap overlap; }; + const tic_outline_item* (*getOutline)(const char* code, s32* size); + const char* blockCommentStart; const char* blockCommentEnd; const char* blockStringStart;