diff --git a/src/code.c b/src/code.c index 441ec12..e989c4c 100644 --- a/src/code.c +++ b/src/code.c @@ -190,189 +190,18 @@ static void updateEditor(Code* code) } } -static inline bool islineend(char c) {return c == '\n' || c == '\0';} -static inline bool isalpha_(char c) {return isalpha(c) || c == '_';} static inline bool isalnum_(char c) {return isalnum(c) || c == '_';} -static void parse(const char* start, u8* color, const tic_script_config* config) -{ - const char* ptr = start; - - const char* blockCommentStart = NULL; - const char* blockStringStart = NULL; - const char* blockStdStringStart = NULL; - const char* singleCommentStart = NULL; - const char* wordStart = NULL; - const char* numberStart = NULL; - - while(true) - { - char c = *ptr; - - if(blockCommentStart) - { - const char* end = strstr(ptr, config->blockCommentEnd); - - ptr = end ? end + strlen(config->blockCommentEnd) : blockCommentStart + strlen(blockCommentStart); - memset(color + (blockCommentStart - start), getConfig()->theme.code.comment, ptr - blockCommentStart); - blockCommentStart = NULL; - continue; - } - else if(blockStringStart) - { - const char* end = strstr(ptr, config->blockStringEnd); - - ptr = end ? end + strlen(config->blockStringEnd) : blockStringStart + strlen(blockStringStart); - memset(color + (blockStringStart - start), getConfig()->theme.code.string, ptr - blockStringStart); - blockStringStart = NULL; - continue; - } - else if(blockStdStringStart) - { - const char* blockStart = blockStdStringStart+1; - - while(true) - { - const char* pos = strchr(blockStart, *blockStdStringStart); - - if(pos) - { - if(*(pos-1) == '\\' && *(pos-2) != '\\') blockStart = pos + 1; - else - { - ptr = pos + 1; - break; - } - } - else - { - ptr = blockStdStringStart + strlen(blockStdStringStart); - break; - } - } - - memset(color + (blockStdStringStart - start), getConfig()->theme.code.string, ptr - blockStdStringStart); - blockStdStringStart = NULL; - continue; - } - else if(singleCommentStart) - { - while(!islineend(*ptr))ptr++; - - memset(color + (singleCommentStart - start), getConfig()->theme.code.comment, ptr - singleCommentStart); - singleCommentStart = NULL; - continue; - } - else if(wordStart) - { - while(!islineend(*ptr) && isalnum_(*ptr)) ptr++; - - s32 len = ptr - wordStart; - bool keyword = false; - { - for(s32 i = 0; i < config->keywordsCount; i++) - if(len == strlen(config->keywords[i]) && memcmp(wordStart, config->keywords[i], len) == 0) - { - memset(color + (wordStart - start), getConfig()->theme.code.keyword, len); - keyword = true; - break; - } - } - - if(!keyword) - { - for(s32 i = 0; i < config->apiCount; i++) - if(len == strlen(config->api[i]) && memcmp(wordStart, config->api[i], len) == 0) - { - memset(color + (wordStart - start), getConfig()->theme.code.api, len); - break; - } - } - - wordStart = NULL; - continue; - } - else if(numberStart) - { - while(!islineend(*ptr)) - { - char c = *ptr; - - if(isdigit(c)) ptr++; - else if(numberStart[0] == '0' - && (numberStart[1] == 'x' || numberStart[1] == 'X') - && isxdigit(numberStart[2])) - { - if((ptr - numberStart < 2) || (ptr - numberStart >= 2 && isxdigit(c))) ptr++; - else break; - } - else if(c == '.' || c == 'e' || c == 'E') - { - if(isdigit(ptr[1])) ptr++; - else break; - } - else break; - } - - memset(color + (numberStart - start), getConfig()->theme.code.number, ptr - numberStart); - numberStart = NULL; - continue; - } - else - { - if(config->blockCommentStart && memcmp(ptr, config->blockCommentStart, strlen(config->blockCommentStart)) == 0) - { - blockCommentStart = ptr; - ptr += strlen(config->blockCommentStart); - continue; - } - if(config->blockStringStart && memcmp(ptr, config->blockStringStart, strlen(config->blockStringStart)) == 0) - { - blockStringStart = ptr; - ptr += strlen(config->blockStringStart); - continue; - } - else if(c == '"' || c == '\'') - { - blockStdStringStart = ptr; - ptr++; - continue; - } - else if(config->singleComment && memcmp(ptr, config->singleComment, strlen(config->singleComment)) == 0) - { - singleCommentStart = ptr; - ptr += strlen(config->singleComment); - continue; - } - else if(isalpha_(c)) - { - wordStart = ptr; - ptr++; - continue; - } - else if(isdigit(c) || (c == '.' && isdigit(ptr[1]))) - { - numberStart = ptr; - ptr++; - continue; - } - else if(ispunct(c)) color[ptr - start] = getConfig()->theme.code.sign; - else if(iscntrl(c)) color[ptr - start] = getConfig()->theme.code.other; - } - - if(!c) break; - - ptr++; - } -} - static void parseSyntaxColor(Code* code) { - memset(code->colorBuffer, getConfig()->theme.code.var, sizeof(code->colorBuffer)); + memset(code->colorBuffer, getConfig()->theme.code.syntax.var, sizeof(code->colorBuffer)); tic_mem* tic = code->tic; - parse(code->src, code->colorBuffer, tic->api.get_script_config(tic)); + const tic_script_config* config = tic->api.get_script_config(tic); + + if(config->parse) + config->parse(config, code->src, code->colorBuffer, &getConfig()->theme.code.syntax); } static char* getLineByPos(Code* code, char* pos) diff --git a/src/config.c b/src/config.c index 1abf7a3..232ea7d 100644 --- a/src/config.c +++ b/src/config.c @@ -101,14 +101,27 @@ static void readCodeTheme(Config* config, lua_State* lua) if(lua_type(lua, -1) == LUA_TTABLE) { - static const char* Fields[] = {"BG", "STRING", "NUMBER", "KEYWORD", "API", "COMMENT", "SIGN", "VAR", "OTHER", "SELECT", "CURSOR"}; + + static const char* Syntax[] = {"STRING", "NUMBER", "KEYWORD", "API", "COMMENT", "SIGN", "VAR", "OTHER"}; + + for(s32 i = 0; i < COUNT_OF(Syntax); i++) + { + lua_getfield(lua, -1, Syntax[i]); + + if(lua_isinteger(lua, -1)) + ((u8*)&config->data.theme.code.syntax)[i] = (u8)lua_tointeger(lua, -1); + + lua_pop(lua, 1); + } + + static const char* Fields[] = {"BG", "SELECT", "CURSOR"}; for(s32 i = 0; i < COUNT_OF(Fields); i++) { lua_getfield(lua, -1, Fields[i]); if(lua_isinteger(lua, -1)) - ((u8*)&config->data.theme.code)[i] = (u8)lua_tointeger(lua, -1); + ((u8*)&config->data.theme.code.bg)[i] = (u8)lua_tointeger(lua, -1); lua_pop(lua, 1); } diff --git a/src/jsapi.c b/src/jsapi.c index 837ce2f..b3cdad0 100644 --- a/src/jsapi.c +++ b/src/jsapi.c @@ -959,6 +959,7 @@ static const tic_script_config JsSyntaxConfig = .overlap = callJavascriptOverlap, .getOutline = getJsOutline, + .parse = parseCode, .blockCommentStart = "/*", .blockCommentEnd = "*/", diff --git a/src/luaapi.c b/src/luaapi.c index 0402a3d..9155f50 100644 --- a/src/luaapi.c +++ b/src/luaapi.c @@ -1386,6 +1386,7 @@ static const tic_script_config LuaSyntaxConfig = .overlap = callLuaOverlap, .getOutline = getLuaOutline, + .parse = parseCode, .blockCommentStart = "--[[", .blockCommentEnd = "]]", @@ -1475,6 +1476,7 @@ static const tic_script_config MoonSyntaxConfig = .overlap = callLuaOverlap, .getOutline = getMoonOutline, + .parse = parseCode, .blockCommentStart = NULL, .blockCommentEnd = NULL, diff --git a/src/machine.h b/src/machine.h index 400b7c9..079ba64 100644 --- a/src/machine.h +++ b/src/machine.h @@ -147,6 +147,7 @@ typedef s32(DrawCharFunc)(tic_mem* memory, u8 symbol, s32 x, s32 y, s32 width, s s32 drawText(tic_mem* memory, const char* text, s32 x, s32 y, s32 width, s32 height, u8 color, s32 scale, DrawCharFunc* func); s32 drawSpriteFont(tic_mem* memory, u8 symbol, s32 x, s32 y, s32 width, s32 height, u8 chromakey, s32 scale); s32 drawFixedSpriteFont(tic_mem* memory, u8 index, s32 x, s32 y, s32 width, s32 height, u8 chromakey, s32 scale); +void parseCode(const tic_script_config* config, const char* start, u8* color, const tic_code_theme* theme); const tic_script_config* getLuaScriptConfig(); const tic_script_config* getMoonScriptConfig(); diff --git a/src/studio.h b/src/studio.h index 97dc34f..4acf49c 100644 --- a/src/studio.h +++ b/src/studio.h @@ -77,15 +77,9 @@ typedef struct struct { + tic_code_theme syntax; + u8 bg; - u8 string; - u8 number; - u8 keyword; - u8 api; - u8 comment; - u8 sign; - u8 var; - u8 other; u8 select; u8 cursor; bool shadow; diff --git a/src/tic.c b/src/tic.c index a1cf36d..c406327 100644 --- a/src/tic.c +++ b/src/tic.c @@ -1906,3 +1906,179 @@ tic_mem* tic_create(s32 samplerate) return &machine->memory; } + +static inline bool islineend(char c) {return c == '\n' || c == '\0';} +static inline bool isalpha_(char c) {return isalpha(c) || c == '_';} +static inline bool isalnum_(char c) {return isalnum(c) || c == '_';} + +void parseCode(const tic_script_config* config, const char* start, u8* color, const tic_code_theme* theme) +{ + const char* ptr = start; + + const char* blockCommentStart = NULL; + const char* blockStringStart = NULL; + const char* blockStdStringStart = NULL; + const char* singleCommentStart = NULL; + const char* wordStart = NULL; + const char* numberStart = NULL; + + while(true) + { + char c = *ptr; + + if(blockCommentStart) + { + const char* end = strstr(ptr, config->blockCommentEnd); + + ptr = end ? end + strlen(config->blockCommentEnd) : blockCommentStart + strlen(blockCommentStart); + memset(color + (blockCommentStart - start), theme->comment, ptr - blockCommentStart); + blockCommentStart = NULL; + continue; + } + else if(blockStringStart) + { + const char* end = strstr(ptr, config->blockStringEnd); + + ptr = end ? end + strlen(config->blockStringEnd) : blockStringStart + strlen(blockStringStart); + memset(color + (blockStringStart - start), theme->string, ptr - blockStringStart); + blockStringStart = NULL; + continue; + } + else if(blockStdStringStart) + { + const char* blockStart = blockStdStringStart+1; + + while(true) + { + const char* pos = strchr(blockStart, *blockStdStringStart); + + if(pos) + { + if(*(pos-1) == '\\' && *(pos-2) != '\\') blockStart = pos + 1; + else + { + ptr = pos + 1; + break; + } + } + else + { + ptr = blockStdStringStart + strlen(blockStdStringStart); + break; + } + } + + memset(color + (blockStdStringStart - start), theme->string, ptr - blockStdStringStart); + blockStdStringStart = NULL; + continue; + } + else if(singleCommentStart) + { + while(!islineend(*ptr))ptr++; + + memset(color + (singleCommentStart - start), theme->comment, ptr - singleCommentStart); + singleCommentStart = NULL; + continue; + } + else if(wordStart) + { + while(!islineend(*ptr) && isalnum_(*ptr)) ptr++; + + s32 len = ptr - wordStart; + bool keyword = false; + { + for(s32 i = 0; i < config->keywordsCount; i++) + if(len == strlen(config->keywords[i]) && memcmp(wordStart, config->keywords[i], len) == 0) + { + memset(color + (wordStart - start), theme->keyword, len); + keyword = true; + break; + } + } + + if(!keyword) + { + for(s32 i = 0; i < config->apiCount; i++) + if(len == strlen(config->api[i]) && memcmp(wordStart, config->api[i], len) == 0) + { + memset(color + (wordStart - start), theme->api, len); + break; + } + } + + wordStart = NULL; + continue; + } + else if(numberStart) + { + while(!islineend(*ptr)) + { + char c = *ptr; + + if(isdigit(c)) ptr++; + else if(numberStart[0] == '0' + && (numberStart[1] == 'x' || numberStart[1] == 'X') + && isxdigit(numberStart[2])) + { + if((ptr - numberStart < 2) || (ptr - numberStart >= 2 && isxdigit(c))) ptr++; + else break; + } + else if(c == '.' || c == 'e' || c == 'E') + { + if(isdigit(ptr[1])) ptr++; + else break; + } + else break; + } + + memset(color + (numberStart - start), theme->number, ptr - numberStart); + numberStart = NULL; + continue; + } + else + { + if(config->blockCommentStart && memcmp(ptr, config->blockCommentStart, strlen(config->blockCommentStart)) == 0) + { + blockCommentStart = ptr; + ptr += strlen(config->blockCommentStart); + continue; + } + if(config->blockStringStart && memcmp(ptr, config->blockStringStart, strlen(config->blockStringStart)) == 0) + { + blockStringStart = ptr; + ptr += strlen(config->blockStringStart); + continue; + } + else if(c == '"' || c == '\'') + { + blockStdStringStart = ptr; + ptr++; + continue; + } + else if(config->singleComment && memcmp(ptr, config->singleComment, strlen(config->singleComment)) == 0) + { + singleCommentStart = ptr; + ptr += strlen(config->singleComment); + continue; + } + else if(isalpha_(c)) + { + wordStart = ptr; + ptr++; + continue; + } + else if(isdigit(c) || (c == '.' && isdigit(ptr[1]))) + { + numberStart = ptr; + ptr++; + continue; + } + else if(ispunct(c)) color[ptr - start] = theme->sign; + else if(iscntrl(c)) color[ptr - start] = theme->other; + } + + if(!c) break; + + ptr++; + } +} \ No newline at end of file diff --git a/src/ticapi.h b/src/ticapi.h index e88467d..d803612 100644 --- a/src/ticapi.h +++ b/src/ticapi.h @@ -75,6 +75,20 @@ typedef struct } tic_outline_item; typedef struct +{ + u8 string; + u8 number; + u8 keyword; + u8 api; + u8 comment; + u8 sign; + u8 var; + u8 other; +} tic_code_theme; + +typedef struct tic_script_config tic_script_config; + +struct tic_script_config { struct { @@ -87,6 +101,7 @@ typedef struct }; const tic_outline_item* (*getOutline)(const char* code, s32* size); + void (*parse)(const tic_script_config* config, const char* start, u8* color, const tic_code_theme* theme); const char* blockCommentStart; const char* blockCommentEnd; @@ -99,7 +114,7 @@ typedef struct const char* const * api; s32 apiCount; -} tic_script_config; +}; typedef struct {