mirror of https://gitlab.com/nakst/essence
scripting engine: replace PrintStdErr with Log; text renderer: syntax highlighting for scripts
This commit is contained in:
parent
2fcb2878fc
commit
13affeb977
|
@ -2,6 +2,11 @@
|
|||
#include <essence.h>
|
||||
#include <shared/array.cpp>
|
||||
|
||||
// TODO:
|
||||
// LogOpenGroup()
|
||||
// LogOpenList()
|
||||
// LogClose()
|
||||
|
||||
struct Instance : EsInstance {
|
||||
EsCommand commandClearOutput;
|
||||
|
||||
|
@ -27,6 +32,7 @@ struct Instance : EsInstance {
|
|||
|
||||
void AddPrompt(Instance *instance);
|
||||
void AddOutput(Instance *instance, const char *text, size_t textBytes);
|
||||
void AddLogOutput(Instance *instance, const char *text, size_t textBytes);
|
||||
|
||||
// --------------------------------- Script engine interface.
|
||||
|
||||
|
@ -159,19 +165,34 @@ CoroutineState *ExternalCoroutineWaitAny(ExecutionContext *context) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int ExternalPrintStdErr(ExecutionContext *context, Value *returnValue) {
|
||||
int ExternalLog(ExecutionContext *context, Value *returnValue) {
|
||||
(void) returnValue;
|
||||
STACK_POP_STRING(entryText, entryBytes);
|
||||
AddOutput(scriptInstance, entryText, entryBytes);
|
||||
AddLogOutput(scriptInstance, entryText, entryBytes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ExternalPrintStdErrWarning(ExecutionContext *context, Value *returnValue) {
|
||||
return ExternalPrintStdErr(context, returnValue);
|
||||
int ExternalTextFormat(ExecutionContext *context, Value *returnValue, const char *mode) {
|
||||
char *buffer = (char *) EsHeapAllocate(16, false);
|
||||
uintptr_t index = HeapAllocate(context);
|
||||
context->heap[index].type = T_STR;
|
||||
context->heap[index].bytes = EsStringFormat(buffer, 16, "%z", mode);
|
||||
context->heap[index].text = buffer;
|
||||
returnValue->i = index;
|
||||
return 3;
|
||||
}
|
||||
|
||||
int ExternalPrintStdErrHighlight(ExecutionContext *context, Value *returnValue) {
|
||||
return ExternalPrintStdErr(context, returnValue);
|
||||
int ExternalTextColorError (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\a#DB002A]"); }
|
||||
int ExternalTextColorHighlight(ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\a#362CB6]"); }
|
||||
int ExternalTextMonospaced (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\am]"); }
|
||||
int ExternalTextPlain (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "\a]"); }
|
||||
|
||||
int ExternalTextWeight(ExecutionContext *context, Value *returnValue) {
|
||||
if (context->c->stackPointer < 1) return -1;
|
||||
int i = context->c->stack[--context->c->stackPointer].i / 100;
|
||||
if (i < 1) i = 1; else if (i > 9) i = 9;
|
||||
char b[5] = { '\a', 'w', (char) (i + '0'), ']', 0 };
|
||||
return ExternalTextFormat(context, returnValue, b);
|
||||
}
|
||||
|
||||
int ExternalSystemSleepMs(ExecutionContext *context, Value *returnValue) {
|
||||
|
@ -693,12 +714,19 @@ void AddREPLResult(ExecutionContext *context, EsElement *parent, Node *type, Val
|
|||
|
||||
uint64_t pngSignature = 0x0A1A0A0D474E5089;
|
||||
uint32_t jpgSignature = 0xE0FFD8FF;
|
||||
bool isPNG = valueBytes > sizeof(pngSignature) && 0 == EsMemoryCompare(&pngSignature, valueText, sizeof(pngSignature));
|
||||
bool isJPG = valueBytes > sizeof(jpgSignature) && 0 == EsMemoryCompare(&jpgSignature, valueText, sizeof(jpgSignature));
|
||||
|
||||
if ((valueBytes > sizeof(pngSignature) && 0 == EsMemoryCompare(&pngSignature, valueText, sizeof(pngSignature)))
|
||||
|| (valueBytes > sizeof(jpgSignature) && 0 == EsMemoryCompare(&jpgSignature, valueText, sizeof(jpgSignature)))) {
|
||||
if (isPNG || isJPG) {
|
||||
EsCanvasPane *canvasPane = EsCanvasPaneCreate(parent, ES_CELL_H_FILL, EsStyleIntern(&styleImageViewerPane));
|
||||
EsImageDisplay *display = EsImageDisplayCreate(canvasPane, ES_CELL_H_LEFT | ES_CELL_V_TOP);
|
||||
EsImageDisplayLoadFromMemory(display, valueText, valueBytes);
|
||||
char *buffer = EsStringAllocateAndFormat(&bytes, "%d by %d pixels \u2027 %z",
|
||||
EsImageDisplayGetImageWidth(display),
|
||||
EsImageDisplayGetImageHeight(display),
|
||||
isPNG ? "PNG" : isJPG ? "JPEG" : "unknown format");
|
||||
EsTextDisplayCreate(parent, ES_CELL_H_FILL, EsStyleIntern(&styleOutputParagraphItalic), buffer, bytes);
|
||||
EsHeapFree(buffer);
|
||||
} else if (EsUTF8IsValid(valueText, valueBytes)) {
|
||||
char *buffer = EsStringAllocateAndFormat(&bytes, "\u201C%s\u201D", valueBytes, valueText);
|
||||
EsTextDisplayCreate(parent, ES_CELL_H_FILL, EsStyleIntern(&styleOutputData), buffer, bytes);
|
||||
|
@ -858,7 +886,8 @@ void EnterCommand(Instance *instance) {
|
|||
|
||||
EsPanel *commandLogRow = EsPanelCreate(instance->root, ES_CELL_H_FILL | ES_PANEL_STACK | ES_PANEL_HORIZONTAL, EsStyleIntern(&styleInputRow));
|
||||
EsTextDisplayCreate(commandLogRow, ES_FLAGS_DEFAULT, EsStyleIntern(&stylePromptText), "\u2661");
|
||||
EsTextDisplayCreate(commandLogRow, ES_CELL_H_FILL, EsStyleIntern(&styleCommandLogText), data, dataBytes);
|
||||
EsTextDisplay *inputCommand = EsTextDisplayCreate(commandLogRow, ES_CELL_H_FILL, EsStyleIntern(&styleCommandLogText), data, dataBytes);
|
||||
EsTextDisplaySetupSyntaxHighlighting(inputCommand, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT);
|
||||
instance->outputElements.Add(commandLogRow);
|
||||
|
||||
EsAssert(!instance->outputPanel);
|
||||
|
@ -891,7 +920,8 @@ void AddOutput(Instance *instance, const char *text, size_t textBytes) {
|
|||
if (text[i] == '\n') {
|
||||
if (EsUTF8IsValid(instance->outputLineBuffer, instance->outputLineBufferBytes)) {
|
||||
EsMessageMutexAcquire();
|
||||
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL, EsStyleIntern(&styleOutputParagraph),
|
||||
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL | ES_TEXT_DISPLAY_RICH_TEXT,
|
||||
EsStyleIntern(&styleOutputParagraph),
|
||||
instance->outputLineBuffer, instance->outputLineBufferBytes);
|
||||
EsMessageMutexRelease();
|
||||
} else {
|
||||
|
@ -900,6 +930,7 @@ void AddOutput(Instance *instance, const char *text, size_t textBytes) {
|
|||
EsLiteral("Encoding error.\n"));
|
||||
EsMessageMutexRelease();
|
||||
}
|
||||
|
||||
instance->outputLineBufferBytes = 0;
|
||||
} else {
|
||||
if (instance->outputLineBufferBytes == instance->outputLineBufferAllocated) {
|
||||
|
@ -913,6 +944,22 @@ void AddOutput(Instance *instance, const char *text, size_t textBytes) {
|
|||
}
|
||||
}
|
||||
|
||||
void AddLogOutput(Instance *instance, const char *text, size_t textBytes) {
|
||||
instance->anyOutput = true;
|
||||
|
||||
if (EsUTF8IsValid(text, textBytes)) {
|
||||
EsMessageMutexAcquire();
|
||||
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL | ES_TEXT_DISPLAY_RICH_TEXT,
|
||||
EsStyleIntern(&styleOutputParagraph), text, textBytes);
|
||||
EsMessageMutexRelease();
|
||||
} else {
|
||||
EsMessageMutexAcquire();
|
||||
EsTextDisplayCreate(instance->outputPanel, ES_CELL_H_FILL,
|
||||
EsStyleIntern(&styleOutputParagraphItalic), EsLiteral("Encoding error.\n"));
|
||||
EsMessageMutexRelease();
|
||||
}
|
||||
}
|
||||
|
||||
void AddPrompt(Instance *instance) {
|
||||
if (instance->outputPanel) {
|
||||
instance->outputElements.Add(EsElementGetLayoutParent(instance->outputPanel));
|
||||
|
@ -928,6 +975,7 @@ void AddPrompt(Instance *instance) {
|
|||
instance->inputRow = EsPanelCreate(instance->root, ES_CELL_H_FILL | ES_PANEL_STACK | ES_PANEL_HORIZONTAL, EsStyleIntern(&styleInputRow));
|
||||
EsTextDisplayCreate(instance->inputRow, ES_FLAGS_DEFAULT, EsStyleIntern(&stylePromptText), "\u2665");
|
||||
instance->inputTextbox = EsTextboxCreate(instance->inputRow, ES_CELL_H_FILL, EsStyleIntern(&styleInputTextbox));
|
||||
EsTextboxSetupSyntaxHighlighting(instance->inputTextbox, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT);
|
||||
EsTextboxEnableSmartReplacement(instance->inputTextbox, false);
|
||||
instance->inputTextbox->messageUser = InputTextboxMessage;
|
||||
EsElementFocus(instance->inputTextbox, ES_ELEMENT_FOCUS_ENSURE_VISIBLE);
|
||||
|
|
|
@ -5822,6 +5822,14 @@ int ProcessImageDisplayMessage(EsElement *element, EsMessage *message) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t EsImageDisplayGetImageWidth(EsImageDisplay *display) {
|
||||
return display->width;
|
||||
}
|
||||
|
||||
uint32_t EsImageDisplayGetImageHeight(EsImageDisplay *display) {
|
||||
return display->height;
|
||||
}
|
||||
|
||||
EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags, EsStyleID style) {
|
||||
EsImageDisplay *display = (EsImageDisplay *) EsHeapAllocate(sizeof(EsImageDisplay), true);
|
||||
if (!display) return nullptr;
|
||||
|
|
|
@ -694,8 +694,9 @@ define ES_ELEMENT_TRANSITION_HIDE_AFTER_COMPLETE (1 << 2)
|
|||
|
||||
define ES_TEXT_GET_CHARACTER_AT_POINT_MIDDLE (1 << 0)
|
||||
|
||||
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C (1)
|
||||
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI (2)
|
||||
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C (1)
|
||||
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI (2)
|
||||
define ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT (3)
|
||||
|
||||
define ES_DRAW_LINE_CAP_ROUND (1 << 0)
|
||||
define ES_DRAW_LINE_CAP_SQUARE (1 << 1)
|
||||
|
@ -2569,6 +2570,8 @@ function EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags
|
|||
function void EsImageDisplayLoadBits(EsImageDisplay *display, const uint32_t *bits, size_t width, size_t height, size_t stride) @matrix_in(bits, width, height);
|
||||
function void EsImageDisplayLoadFromMemory(EsImageDisplay *display, const void *buffer, size_t bufferBytes) @buffer_in(buffer, bufferBytes);
|
||||
function void EsImageDisplayPaint(EsImageDisplay *display, EsPainter *painter, EsRectangle bounds);
|
||||
function uint32_t EsImageDisplayGetImageWidth(EsImageDisplay *display);
|
||||
function uint32_t EsImageDisplayGetImageHeight(EsImageDisplay *display);
|
||||
|
||||
function EsTextDisplay *EsTextDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, EsStyleID style = 0, STRING label = BLANK_STRING);
|
||||
function void EsTextDisplaySetContents(EsTextDisplay *display, STRING contents = BLANK_STRING);
|
||||
|
|
132
desktop/text.cpp
132
desktop/text.cpp
|
@ -2548,6 +2548,9 @@ void EsDrawTextThemed(EsPainter *painter, EsElement *element, EsRectangle bounds
|
|||
void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
|
||||
char **outString, EsTextRun **outTextRuns, size_t *outTextRunCount,
|
||||
EsTextStyle *baseStyle) {
|
||||
// TODO Check that this can be used on untrusted input.
|
||||
// Specifically, what if textRunCount/stringBytes are calculated incorrectly?
|
||||
|
||||
if (inStringBytes == -1) {
|
||||
inStringBytes = EsCStringLength(inString);
|
||||
}
|
||||
|
@ -2597,15 +2600,17 @@ void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
|
|||
if (c == ']') {
|
||||
break;
|
||||
} else if (c == 'w' /* weight */) {
|
||||
i++; if (i >= inStringBytes || inString[i] == ']') goto parsedFormat;
|
||||
textRun->style.font.weight = inString[i] - '0';
|
||||
i++;
|
||||
if (i >= inStringBytes || inString[i] == ']') {}
|
||||
else textRun->style.font.weight = inString[i] - '0';
|
||||
} else if (c == 'i' /* italic */) {
|
||||
textRun->style.font.flags |= ES_FONT_ITALIC;
|
||||
} else if (c == 's' /* size */) {
|
||||
textRun->style.size = 0;
|
||||
|
||||
while (true) {
|
||||
i++; if (i >= inStringBytes || inString[i] == ']') goto parsedFormat;
|
||||
i++;
|
||||
if (i >= inStringBytes || inString[i] == ']') break;
|
||||
if (inString[i] < '0' || inString[i] > '9') { i--; break; }
|
||||
textRun->style.size *= 10;
|
||||
textRun->style.size += inString[i] - '0';
|
||||
|
@ -2627,12 +2632,11 @@ void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
|
|||
string[bytes++] = inString[i++];
|
||||
}
|
||||
|
||||
i--;
|
||||
textRun->style.color = EsColorParse(string, bytes);
|
||||
goto parsedFormat;
|
||||
}
|
||||
}
|
||||
|
||||
parsedFormat:;
|
||||
textRunIndex++;
|
||||
} else {
|
||||
string[stringIndex++] = inString[i];
|
||||
|
@ -2650,41 +2654,84 @@ void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
|
|||
|
||||
// --------------------------------- Syntax highlighting.
|
||||
|
||||
const char *const keywords_a[] = { "auto", nullptr };
|
||||
const char *const keywords_b[] = { "bool", "break", nullptr };
|
||||
const char *const keywords_c[] = { "case", "char", "const", "continue", nullptr };
|
||||
const char *const keywords_d[] = { "default", "do", "double", nullptr };
|
||||
const char *const keywords_e[] = { "else", "enum", "extern", nullptr };
|
||||
const char *const keywords_f[] = { "float", "for", nullptr };
|
||||
const char *const keywords_g[] = { "goto", nullptr };
|
||||
const char *const keywords_h[] = { nullptr };
|
||||
const char *const keywords_i[] = { "if", "inline", "int", "int16_t", "int32_t", "int64_t", "int8_t", "intptr_t", nullptr };
|
||||
const char *const keywords_j[] = { nullptr };
|
||||
const char *const keywords_k[] = { nullptr };
|
||||
const char *const keywords_l[] = { "long", nullptr };
|
||||
const char *const keywords_m[] = { nullptr };
|
||||
const char *const keywords_n[] = { nullptr };
|
||||
const char *const keywords_o[] = { nullptr };
|
||||
const char *const keywords_p[] = { nullptr };
|
||||
const char *const keywords_q[] = { nullptr };
|
||||
const char *const keywords_r[] = { "register", "restrict", "return", nullptr };
|
||||
const char *const keywords_s[] = { "short", "signed", "sizeof", "static", "struct", "switch", nullptr };
|
||||
const char *const keywords_t[] = { "typedef", nullptr };
|
||||
const char *const keywords_u[] = { "uint16_t", "uint32_t", "uint64_t", "uint8_t", "uintptr_t", "union", "unsigned", nullptr };
|
||||
const char *const keywords_v[] = { "void", "volatile", nullptr };
|
||||
const char *const keywords_w[] = { "while", nullptr };
|
||||
const char *const keywords_x[] = { nullptr };
|
||||
const char *const keywords_y[] = { nullptr };
|
||||
const char *const keywords_z[] = { nullptr };
|
||||
const char *const keywordsC_a[] = { "auto", nullptr };
|
||||
const char *const keywordsC_b[] = { "bool", "break", nullptr };
|
||||
const char *const keywordsC_c[] = { "case", "char", "const", "continue", nullptr };
|
||||
const char *const keywordsC_d[] = { "default", "do", "double", nullptr };
|
||||
const char *const keywordsC_e[] = { "else", "enum", "extern", nullptr };
|
||||
const char *const keywordsC_f[] = { "float", "for", nullptr };
|
||||
const char *const keywordsC_g[] = { "goto", nullptr };
|
||||
const char *const keywordsC_h[] = { nullptr };
|
||||
const char *const keywordsC_i[] = { "if", "inline", "int", "int16_t", "int32_t", "int64_t", "int8_t", "intptr_t", nullptr };
|
||||
const char *const keywordsC_j[] = { nullptr };
|
||||
const char *const keywordsC_k[] = { nullptr };
|
||||
const char *const keywordsC_l[] = { "long", nullptr };
|
||||
const char *const keywordsC_m[] = { nullptr };
|
||||
const char *const keywordsC_n[] = { nullptr };
|
||||
const char *const keywordsC_o[] = { nullptr };
|
||||
const char *const keywordsC_p[] = { nullptr };
|
||||
const char *const keywordsC_q[] = { nullptr };
|
||||
const char *const keywordsC_r[] = { "register", "restrict", "return", nullptr };
|
||||
const char *const keywordsC_s[] = { "short", "signed", "sizeof", "static", "struct", "switch", nullptr };
|
||||
const char *const keywordsC_t[] = { "typedef", nullptr };
|
||||
const char *const keywordsC_u[] = { "uint16_t", "uint32_t", "uint64_t", "uint8_t", "uintptr_t", "union", "unsigned", nullptr };
|
||||
const char *const keywordsC_v[] = { "void", "volatile", nullptr };
|
||||
const char *const keywordsC_w[] = { "while", nullptr };
|
||||
const char *const keywordsC_x[] = { nullptr };
|
||||
const char *const keywordsC_y[] = { nullptr };
|
||||
const char *const keywordsC_z[] = { nullptr };
|
||||
|
||||
const char *const *const keywords[] = {
|
||||
keywords_a, keywords_b, keywords_c, keywords_d,
|
||||
keywords_e, keywords_f, keywords_g, keywords_h,
|
||||
keywords_i, keywords_j, keywords_k, keywords_l,
|
||||
keywords_m, keywords_n, keywords_o, keywords_p,
|
||||
keywords_q, keywords_r, keywords_s, keywords_t,
|
||||
keywords_u, keywords_v, keywords_w, keywords_x,
|
||||
keywords_y, keywords_z,
|
||||
const char *const keywordsScript_a[] = { "assert", "await", nullptr };
|
||||
const char *const keywordsScript_b[] = { "bool", nullptr };
|
||||
const char *const keywordsScript_c[] = { nullptr };
|
||||
const char *const keywordsScript_d[] = { nullptr };
|
||||
const char *const keywordsScript_e[] = { "else", nullptr };
|
||||
const char *const keywordsScript_f[] = { "false", "float", "for", "functype", nullptr };
|
||||
const char *const keywordsScript_g[] = { nullptr };
|
||||
const char *const keywordsScript_h[] = { nullptr };
|
||||
const char *const keywordsScript_i[] = { "if", "int", nullptr };
|
||||
const char *const keywordsScript_j[] = { nullptr };
|
||||
const char *const keywordsScript_k[] = { nullptr };
|
||||
const char *const keywordsScript_l[] = { nullptr };
|
||||
const char *const keywordsScript_m[] = { nullptr };
|
||||
const char *const keywordsScript_n[] = { "new", "null", nullptr };
|
||||
const char *const keywordsScript_o[] = { nullptr };
|
||||
const char *const keywordsScript_p[] = { nullptr };
|
||||
const char *const keywordsScript_q[] = { nullptr };
|
||||
const char *const keywordsScript_r[] = { "return", nullptr };
|
||||
const char *const keywordsScript_s[] = { "str", "struct", nullptr };
|
||||
const char *const keywordsScript_t[] = { "true", "tuple", nullptr };
|
||||
const char *const keywordsScript_u[] = { nullptr };
|
||||
const char *const keywordsScript_v[] = { "void", nullptr };
|
||||
const char *const keywordsScript_w[] = { "while", nullptr };
|
||||
const char *const keywordsScript_x[] = { nullptr };
|
||||
const char *const keywordsScript_y[] = { nullptr };
|
||||
const char *const keywordsScript_z[] = { nullptr };
|
||||
|
||||
const char *const *const keywordsC[] = {
|
||||
keywordsC_a, keywordsC_b, keywordsC_c, keywordsC_d,
|
||||
keywordsC_e, keywordsC_f, keywordsC_g, keywordsC_h,
|
||||
keywordsC_i, keywordsC_j, keywordsC_k, keywordsC_l,
|
||||
keywordsC_m, keywordsC_n, keywordsC_o, keywordsC_p,
|
||||
keywordsC_q, keywordsC_r, keywordsC_s, keywordsC_t,
|
||||
keywordsC_u, keywordsC_v, keywordsC_w, keywordsC_x,
|
||||
keywordsC_y, keywordsC_z,
|
||||
};
|
||||
|
||||
const char *const *const keywordsScript[] = {
|
||||
keywordsScript_a, keywordsScript_b, keywordsScript_c, keywordsScript_d,
|
||||
keywordsScript_e, keywordsScript_f, keywordsScript_g, keywordsScript_h,
|
||||
keywordsScript_i, keywordsScript_j, keywordsScript_k, keywordsScript_l,
|
||||
keywordsScript_m, keywordsScript_n, keywordsScript_o, keywordsScript_p,
|
||||
keywordsScript_q, keywordsScript_r, keywordsScript_s, keywordsScript_t,
|
||||
keywordsScript_u, keywordsScript_v, keywordsScript_w, keywordsScript_x,
|
||||
keywordsScript_y, keywordsScript_z,
|
||||
};
|
||||
|
||||
const char *const *const *const keywords[] = {
|
||||
keywordsC,
|
||||
nullptr /* INI */,
|
||||
keywordsScript,
|
||||
};
|
||||
|
||||
bool CharIsAlphaOrDigitOrUnderscore(char c) {
|
||||
|
@ -2693,7 +2740,6 @@ bool CharIsAlphaOrDigitOrUnderscore(char c) {
|
|||
|
||||
Array<EsTextRun> TextApplySyntaxHighlighting(const EsTextStyle *baseStyle, int language, uint32_t *colors, Array<EsTextRun> runs, const char *string, size_t bytes) {
|
||||
// TODO Make these colors customizable!
|
||||
// TODO Highlight keywords.
|
||||
|
||||
int lexState = 0;
|
||||
bool inComment = false, inIdentifier = false, inChar = false, startedString = false;
|
||||
|
@ -2713,14 +2759,14 @@ Array<EsTextRun> TextApplySyntaxHighlighting(const EsTextStyle *baseStyle, int l
|
|||
last = 0;
|
||||
}
|
||||
|
||||
if (language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C) {
|
||||
if (language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C || language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT) {
|
||||
if (lexState == 4) {
|
||||
lexState = 0;
|
||||
} else if (lexState == 1) {
|
||||
if ((last & 0xFF0000) == ('*' << 16) && (last & 0xFF00) == ('/' << 8) && inComment) {
|
||||
lexState = 0, inComment = false;
|
||||
}
|
||||
} else if (lexState == 3 || lexState == 6) {
|
||||
} else if (lexState == 3 || lexState == 6 || (lexState == 5 && language == ES_SYNTAX_HIGHLIGHTING_LANGUAGE_SCRIPT)) {
|
||||
if (!CharIsAlphaOrDigitOrUnderscore(c)) {
|
||||
lexState = 0;
|
||||
}
|
||||
|
@ -2760,7 +2806,7 @@ Array<EsTextRun> TextApplySyntaxHighlighting(const EsTextStyle *baseStyle, int l
|
|||
inIdentifier = true;
|
||||
|
||||
if (c >= 'a' && c <= 'z' && (!index || !CharIsAlphaOrDigitOrUnderscore(string[index - 1]))) {
|
||||
const char *const *k = keywords[c - 'a'];
|
||||
const char *const *k = keywords[language - 1][c - 'a'];
|
||||
|
||||
for (int i = 0; k[i]; i++) {
|
||||
int j = 0;
|
||||
|
|
|
@ -170,14 +170,14 @@ void PortMesa() {
|
|||
void PortGCC() {
|
||||
if buildCross {
|
||||
// Print instructions.
|
||||
PrintStdErr("To build Essence, you need a cross compiler. This will be built for you automatically.\n");
|
||||
PrintStdErr("- You need to be connected to the internet. ~100MB will be downloaded.\n");
|
||||
PrintStdErr("- You need ~3GB of drive space available.\n");
|
||||
PrintStdErr("- You need ~8GB of RAM available.\n");
|
||||
PrintStdErr("- This should take ~20 minutes on a modern computer.\n");
|
||||
PrintStdErr("- This does *not* require root permissions.\n");
|
||||
PrintStdErr("- You must fully update your system before building.\n");
|
||||
PrintStdErr("Enter 'yes' to continue.\n");
|
||||
Log("To build Essence, you need a cross compiler. This will be built for you automatically.");
|
||||
Log("- You need to be connected to the internet. ~100MB will be downloaded.");
|
||||
Log("- You need ~3GB of drive space available.");
|
||||
Log("- You need ~8GB of RAM available.");
|
||||
Log("- This should take ~20 minutes on a modern computer.");
|
||||
Log("- This does *not* require root permissions.");
|
||||
Log("- You must fully update your system before building.");
|
||||
Log("Enter 'yes' to continue.");
|
||||
assert ConsoleGetYes();
|
||||
}
|
||||
|
||||
|
@ -234,8 +234,8 @@ void PortGCC() {
|
|||
// Ask the user if they want to resume an incomplete build.
|
||||
bool resumeBuild = false;
|
||||
if runningMakefiles {
|
||||
PrintStdErr("The build system has detected a build was started, but was not completed.\n");
|
||||
PrintStdErr("Enter 'yes' to attempt to resume this build.\n");
|
||||
Log("The build system has detected a build was started, but was not completed.");
|
||||
Log("Enter 'yes' to attempt to resume this build.");
|
||||
resumeBuild = ConsoleGetYes();
|
||||
runningMakefiles = false;
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ void PortGCC() {
|
|||
PathDeleteRecursively("bin/mpc-src");
|
||||
PathDeleteRecursively("bin/mpfr-src");
|
||||
PathDeleteRecursively("bin/gmp-src");
|
||||
PrintStdErrHighlight("Build succeeded.\n");
|
||||
LogInfo("Build succeeded.");
|
||||
}
|
||||
|
||||
void PortFreeType() {
|
||||
|
@ -618,24 +618,24 @@ void Start() {
|
|||
PortCallback[] portCallbacks = [ PortFFmpeg, PortUxn, PortNasm, PortBochs, PortBusybox, PortMesa, PortGCC, PortFreeType, PortHarfBuzz, PortMusl ];
|
||||
|
||||
if portName == "" {
|
||||
PrintStdErrHighlight("Available ports:\n");
|
||||
LogInfo("Available ports:");
|
||||
|
||||
for int i = 0; i < portNames:len(); i += 1 {
|
||||
PrintStdErr("\t%portNames[i]%\n");
|
||||
Log("\t%portNames[i]%");
|
||||
}
|
||||
} else {
|
||||
assert targetName != "";
|
||||
assert toolchainPrefix != "";
|
||||
|
||||
// PrintStdErrHighlight("Target name: '%targetName%'\n");
|
||||
// PrintStdErrHighlight("Toolchain prefix: '%toolchainPrefix%'\n");
|
||||
// PrintStdErrHighlight("Processors to use for compilation: '%processorCount%'\n");
|
||||
// PrintStdErrHighlight("Skip yes checks: '%skipYesChecks%'\n");
|
||||
// LogInfo("Target name: '%targetName%'");
|
||||
// LogInfo("Toolchain prefix: '%toolchainPrefix%'");
|
||||
// LogInfo("Processors to use for compilation: '%processorCount%'");
|
||||
// LogInfo("Skip yes checks: '%skipYesChecks%'");
|
||||
|
||||
for int i = 0; i < portNames:len(); i += 1 {
|
||||
if portNames[i] == portName || portName == "all" {
|
||||
if portName == "all" {
|
||||
PrintStdErrHighlight("Building port: '%portNames[i]%'\n");
|
||||
LogInfo("Building port: '%portNames[i]%'");
|
||||
}
|
||||
|
||||
portCallbacks[i]();
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 426 KiB After Width: | Height: | Size: 426 KiB |
|
@ -456,6 +456,7 @@ _EsUISetFont=454
|
|||
EsWorkQueue=455
|
||||
EsWorkIsExiting=456
|
||||
EsPanelRadioGroupGetChecked=457
|
||||
EsImageDisplayGetImageWidth=458
|
||||
EsBufferWriteInt8=459
|
||||
EsInstanceGetStartupRequest=460
|
||||
EsImageDisplayPaint=461
|
||||
|
@ -492,3 +493,4 @@ _EsDebugCommand=491
|
|||
DateToLinear=492
|
||||
EsRectangleContainsAll=493
|
||||
EsListViewFixedItemSetEnumStringsForColumn=494
|
||||
EsImageDisplayGetImageHeight=495
|
||||
|
|
|
@ -25,9 +25,9 @@ void Get(str url, str directoryName, str checksum) {
|
|||
if checksum != "" {
|
||||
// If we're verifying the checksum of the file, then it should be okay to try downloading it from a non-official mirror.
|
||||
alternateURL = "https://github.com/nakst/cdn/raw/main/cache/" + url2;
|
||||
PrintStdErr("Attempting to download from '%alternateURL%' with fallback '%url%'...\n");
|
||||
Log("Attempting to download from '%alternateURL%' with fallback '%url%'...");
|
||||
} else {
|
||||
PrintStdErr("Attempting to download from '%url%'...\n");
|
||||
Log("Attempting to download from '%url%'...");
|
||||
}
|
||||
|
||||
bool got = PathExists(cachePath);
|
||||
|
@ -37,18 +37,18 @@ void Get(str url, str directoryName, str checksum) {
|
|||
|
||||
if !got {
|
||||
PathDelete(cachePath);
|
||||
PrintStdErrWarning("Error: Could not download the file at '%url%'. Exiting.\n");
|
||||
LogError("Could not download the file at '%url%'. Exiting.\n");
|
||||
assert false;
|
||||
}
|
||||
|
||||
if checksum != "" {
|
||||
if SystemShellEvaluate("shasum -a 256 %cachePath%") != "%checksum% %cachePath%\n" {
|
||||
PrintStdErrWarning("Error: Checksum mismatch for file '%cachePath%'.\n");
|
||||
LogError("Checksum mismatch for file '%cachePath%'.\n");
|
||||
PathDelete(cachePath);
|
||||
assert false;
|
||||
}
|
||||
|
||||
PrintStdErr("Valid checksum.\n");
|
||||
Log("Valid checksum.");
|
||||
}
|
||||
|
||||
str decompressFlag = "";
|
||||
|
@ -60,14 +60,14 @@ void Get(str url, str directoryName, str checksum) {
|
|||
} else if StringContains(url, ".tar.gz") {
|
||||
decompressFlag = "z";
|
||||
} else {
|
||||
PrintStdErrWarning("Error: Unrecognised archive format extension.\n");
|
||||
LogError("Unrecognised archive format extension.\n");
|
||||
assert false;
|
||||
}
|
||||
|
||||
assert SystemShellExecute("tar -x%decompressFlag%f %cachePath%");
|
||||
assert PathMove(directoryName, "bin/source");
|
||||
|
||||
PrintStdErr("File successfully downloaded and extracted.\n");
|
||||
Log("File successfully downloaded and extracted.");
|
||||
}
|
||||
|
||||
void Start() {
|
||||
|
|
|
@ -437,9 +437,16 @@ char baseModuleSource[] = {
|
|||
|
||||
// Logging:
|
||||
|
||||
"void PrintStdErr(str x) #extcall;"
|
||||
"void PrintStdErrWarning(str x) #extcall;"
|
||||
"void PrintStdErrHighlight(str x) #extcall;"
|
||||
"void Log(str x) #extcall;"
|
||||
"void LogInfo(str x) { Log(TextColorHighlight() + x); }"
|
||||
"void LogError(str x) { Log(TextColorError() + \"Error: \" + x); }"
|
||||
|
||||
"str TextColorError() #extcall;"
|
||||
"str TextColorHighlight() #extcall;"
|
||||
"str TextWeight(int i) #extcall;"
|
||||
"str TextMonospaced() #extcall;"
|
||||
"str TextPlain() #extcall;"
|
||||
"str TextBold() { return TextWeight(700); }"
|
||||
|
||||
// String operations:
|
||||
|
||||
|
@ -691,9 +698,12 @@ char baseModuleSource[] = {
|
|||
|
||||
// --------------------------------- External function calls.
|
||||
|
||||
int ExternalPrintStdErr(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalPrintStdErrWarning(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalPrintStdErrHighlight(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalLog(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalTextColorError(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalTextColorHighlight(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalTextWeight(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalTextMonospaced(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalTextPlain(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalConsoleGetLine(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalStringSlice(ExecutionContext *context, Value *returnValue);
|
||||
int ExternalCharacterToByte(ExecutionContext *context, Value *returnValue);
|
||||
|
@ -730,9 +740,12 @@ int External_DirectoryInternalEndIteration(ExecutionContext *context, Value *ret
|
|||
int ExternalOpenDocumentEnumerate(ExecutionContext *context, Value *returnValue);
|
||||
|
||||
ExternalFunction externalFunctions[] = {
|
||||
{ .cName = "PrintStdErr", .callback = ExternalPrintStdErr },
|
||||
{ .cName = "PrintStdErrWarning", .callback = ExternalPrintStdErrWarning },
|
||||
{ .cName = "PrintStdErrHighlight", .callback = ExternalPrintStdErrHighlight },
|
||||
{ .cName = "Log", .callback = ExternalLog },
|
||||
{ .cName = "TextColorError", .callback = ExternalTextColorError },
|
||||
{ .cName = "TextColorHighlight", .callback = ExternalTextColorHighlight },
|
||||
{ .cName = "TextWeight", .callback = ExternalTextWeight },
|
||||
{ .cName = "TextMonospaced", .callback = ExternalTextMonospaced },
|
||||
{ .cName = "TextPlain", .callback = ExternalTextPlain },
|
||||
{ .cName = "ConsoleGetLine", .callback = ExternalConsoleGetLine },
|
||||
{ .cName = "StringSlice", .callback = ExternalStringSlice },
|
||||
{ .cName = "CharacterToByte", .callback = ExternalCharacterToByte },
|
||||
|
@ -5363,6 +5376,7 @@ pthread_mutex_t externalCoroutineMutex;
|
|||
CoroutineState *externalCoroutineUnblockedList;
|
||||
|
||||
bool systemShellLoggingEnabled = true;
|
||||
bool coloredOutput;
|
||||
|
||||
char *scriptSourceDirectory;
|
||||
|
||||
|
@ -5552,33 +5566,36 @@ int ExternalSystemShellEnableLogging(ExecutionContext *context, Value *returnVal
|
|||
return 1;
|
||||
}
|
||||
|
||||
int ExternalPrintStdErr(ExecutionContext *context, Value *returnValue) {
|
||||
(void) returnValue;
|
||||
int ExternalLog(ExecutionContext *context, Value *returnValue) {
|
||||
STACK_POP_STRING(entryText, entryBytes);
|
||||
fprintf(stderr, "%.*s", (int) entryBytes, (char *) entryText);
|
||||
fprintf(stderr, coloredOutput ? "\033[0;m\n" : "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ExternalPrintStdErrWarning(ExecutionContext *context, Value *returnValue) {
|
||||
(void) returnValue;
|
||||
STACK_POP_STRING(entryText, entryBytes);
|
||||
static int coloredOutput = 0;
|
||||
#ifndef _WIN32
|
||||
if (!coloredOutput) coloredOutput = isatty(STDERR_FILENO) ? 2 : 1;
|
||||
#endif
|
||||
fprintf(stderr, coloredOutput == 2 ? "\033[0;33m%.*s\033[0;m" : "%.*s", (int) entryBytes, (char *) entryText);
|
||||
return 1;
|
||||
int ExternalTextFormat(ExecutionContext *context, Value *returnValue, const char *mode) {
|
||||
if (coloredOutput) {
|
||||
char *buffer = malloc(32);
|
||||
uintptr_t index = HeapAllocate(context);
|
||||
context->heap[index].type = T_STR;
|
||||
context->heap[index].bytes = sprintf(buffer, "\033[0;%sm", mode);
|
||||
context->heap[index].text = buffer;
|
||||
returnValue->i = index;
|
||||
} else {
|
||||
returnValue->i = 0;
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int ExternalPrintStdErrHighlight(ExecutionContext *context, Value *returnValue) {
|
||||
(void) returnValue;
|
||||
STACK_POP_STRING(entryText, entryBytes);
|
||||
static int coloredOutput = 0;
|
||||
#ifndef _WIN32
|
||||
if (!coloredOutput) coloredOutput = isatty(STDERR_FILENO) ? 2 : 1;
|
||||
#endif
|
||||
fprintf(stderr, coloredOutput == 2 ? "\033[0;36m%.*s\033[0;m" : "%.*s", (int) entryBytes, (char *) entryText);
|
||||
return 1;
|
||||
int ExternalTextColorError (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "31"); }
|
||||
int ExternalTextColorHighlight(ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, "36"); }
|
||||
int ExternalTextMonospaced (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, ""); }
|
||||
int ExternalTextPlain (ExecutionContext *context, Value *returnValue) { return ExternalTextFormat(context, returnValue, ""); }
|
||||
|
||||
int ExternalTextWeight(ExecutionContext *context, Value *returnValue) {
|
||||
if (context->c->stackPointer < 1) return -1;
|
||||
return ExternalTextFormat(context, returnValue, context->c->stack[--context->c->stackPointer].i > 500 ? "1" : "");
|
||||
}
|
||||
|
||||
int ExternalPathCreateDirectory(ExecutionContext *context, Value *returnValue) {
|
||||
|
@ -6240,8 +6257,8 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
coloredOutput = isatty(STDERR_FILENO);
|
||||
srand(time(NULL));
|
||||
|
||||
sem_init(&externalCoroutineSemaphore, 0, 0);
|
||||
|
||||
char *scriptPath = NULL;
|
||||
|
|
|
@ -13,28 +13,28 @@ void Setup(bool forAutomation) {
|
|||
assert PathCreateLeadingDirectories("bin/Object Files");
|
||||
|
||||
if SystemGetHostName() == "Cygwin" {
|
||||
PrintStdErrWarning("Building on Cygwin is not supported. Use the Windows Subsystem for Linux instead.\n");
|
||||
LogError("Building on Cygwin is not supported. Use the Windows Subsystem for Linux instead.");
|
||||
assert false;
|
||||
}
|
||||
|
||||
if SystemShellEvaluate("shasum -a 256 util/test.txt")
|
||||
!= "2c5622dbbf2552e0e66424a302bde0918e09379afce47eef1a21ef0198990fed util/test.txt\n" {
|
||||
PrintStdErrWarning("--------------------------------------------------------------------\n");
|
||||
PrintStdErrWarning(" The source has been corrupted!! \n");
|
||||
PrintStdErrWarning(" Please check that you have disabled any automatic line-ending or \n");
|
||||
PrintStdErrWarning(" encoding conversions in Git and archive extraction tools you use. \n");
|
||||
PrintStdErrWarning("--------------------------------------------------------------------\n");
|
||||
Log(TextColorError() + "--------------------------------------------------------------------");
|
||||
Log(TextColorError() + " The source has been corrupted!! ");
|
||||
Log(TextColorError() + " Please check that you have disabled any automatic line-ending or ");
|
||||
Log(TextColorError() + " encoding conversions in Git and archive extraction tools you use. ");
|
||||
Log(TextColorError() + "--------------------------------------------------------------------");
|
||||
assert false;
|
||||
}
|
||||
|
||||
if StringContains(PathGetDefaultPrefix(), " ") {
|
||||
PrintStdErrWarning("Error: The path to your essence directory, '%PathGetDefaultPrefix()%', contains spaces.\n");
|
||||
LogError("The path to your essence directory, '%PathGetDefaultPrefix()%', contains spaces.");
|
||||
assert false;
|
||||
}
|
||||
|
||||
if !SystemShellExecute("which gcc > /dev/null") { PrintStdErrWarning("Error: GCC was not found.\n"); assert false; }
|
||||
if !SystemShellExecute("which nasm > /dev/null") { PrintStdErrWarning("Error: Nasm was not found.\n"); assert false; }
|
||||
if !SystemShellExecute("which make > /dev/null") { PrintStdErrWarning("Error: Make was not found.\n"); assert false; }
|
||||
if !SystemShellExecute("which gcc > /dev/null") { LogError("GCC was not found."); assert false; }
|
||||
if !SystemShellExecute("which nasm > /dev/null") { LogError("Nasm was not found."); assert false; }
|
||||
if !SystemShellExecute("which make > /dev/null") { LogError("Make was not found."); assert false; }
|
||||
|
||||
if target == "" {
|
||||
target = "TARGET_X86_64";
|
||||
|
@ -54,7 +54,7 @@ void Setup(bool forAutomation) {
|
|||
void Start() {
|
||||
Setup(false);
|
||||
SystemShellExecute("bin/build %options%");
|
||||
PrintStdErrHighlight("\n");
|
||||
Log("");
|
||||
}
|
||||
|
||||
void GenerateOVF() {
|
||||
|
|
Loading…
Reference in New Issue