X-Git-Url: https://gitweb.ps.run/iftint/blobdiff_plain/019601bd93d99698c528f57a6a356944b1e46517..5ac301b38e25d0080849a1e60cdc115c33edf87d:/main2.c diff --git a/main2.c b/main2.c index 47e11ee..80f6a17 100644 --- a/main2.c +++ b/main2.c @@ -2,6 +2,11 @@ #include #include #include +#include + +/* TODO +- whitelist input on GetStr/GetInt +*/ // Memory @@ -9,11 +14,33 @@ #define NEWARR(TYPE, NUM) ((TYPE *)calloc(NUM, sizeof(TYPE))) -// getch() +// Util + +bool +charInString(char c, const char * str) { + for (int i = 0; i < strlen(str); i++) + if (c == str[i]) + return true; + return false; +} + +bool +isNewline(char c) { + return c == '\n' || c == '\r'; +} +bool +isBackspace(char c) { + return c == 8 || c == 127; +} + + +// getch #ifdef _WIN32 +#include #include #else +#include #include #include #include @@ -25,21 +52,7 @@ int getch(void) int ch; tcgetattr( STDIN_FILENO, &oldattr ); newattr = oldattr; - newattr.c_lflag &= ~( ICANON | ECHO ); - tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); - ch = getchar(); - tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); - return ch; -} - -/* reads from keypress, echoes */ -int getche(void) -{ - struct termios oldattr, newattr; - int ch; - tcgetattr( STDIN_FILENO, &oldattr ); - newattr = oldattr; - newattr.c_lflag &= ~( ICANON ); + newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?) tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); @@ -85,14 +98,42 @@ void vt100CursorHome() { vt100Escape("[H"); } void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); } void vt100SaveCursor() { vt100Escape("7"); } void vt100RestoreCursor() { vt100Escape("8"); } +// void vt100GetCursor(int * v, int * h) { +// *v = *h = 0; +// printf("\033[6n"); +// getch(); getch(); +// int c; +// while ((c = getch()) != ';') +// *v = (10*(*v)+(c-'0')); +// while ((c = getch()) != 'R') +// *h = (10*(*h)+(c-'0')); +// } +void vt100GetScreenSize(int * v, int * h) { +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); + *h = csbi.srWindow.Right - csbi.srWindow.Left + 1; + *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; +#else + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + *h = w.ws_row; + *v = w.ws_col; +#endif +} +void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); } +void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); } // JSON typedef enum { JSONNodeKind_Nul, + JSONNodeKind_Int, JSONNodeKind_Str, JSONNodeKind_Obj, + JSONNodeKind_Arr, + JSONNodeKind_COUNT } JSONNodeKind; struct JSONNode; @@ -100,50 +141,53 @@ typedef struct JSONNode { JSONNodeKind kind; size_t data; struct JSONNode * parent; - struct JSONNode * children; + struct JSONNode * firstChild; + int childCount; + struct JSONNode * prev; struct JSONNode * next; } JSONNode; JSONNode * -JSONNodeNew(JSONNodeKind kind, size_t data) { +JSONNodeNew(JSONNodeKind kind) { JSONNode * result = NEW(JSONNode); result->kind = kind; - result->data = data; return result; } JSONNode * -JSONNodeNewStr(const char * str) { - return JSONNodeNew(JSONNodeKind_Str, (size_t)str); -} - -JSONNode * -JSONNodeNewObj() { - return JSONNodeNew(JSONNodeKind_Obj, (size_t)NULL); -} - -JSONNode * -JSONNodeNewNul() { - return JSONNodeNew(JSONNodeKind_Nul, (size_t)NULL); -} - -JSONNode * -JSONNodeAppend(JSONNode * this, JSONNode * that) { - if (this->children == NULL) { - this->children = that; +JSONNodePush(JSONNode * this, JSONNode * that) { + if (this->firstChild == NULL) { + this->firstChild = that; } else { - JSONNode * lastNode = this->children; + JSONNode * lastNode = this->firstChild; while (lastNode->next != NULL) lastNode = lastNode->next; lastNode->next = that; + that->prev = lastNode; } + this->childCount++; that->parent = this; - that->next = NULL; return that; } +JSONNode * +JSONNodeRemove(JSONNode * node) { + if (node->prev == NULL) { // first child + node->parent->firstChild = node->next; + if (node->next != NULL) + node->next->prev = NULL; + return node->parent; + } + else { // second child + node->prev->next = node->next; + if (node->next != NULL) + node->next->prev = node->prev; + return node->prev; + } +} + void Indent(int indent) { for (int i = 0; i < indent; i++) @@ -151,19 +195,28 @@ Indent(int indent) { } void -JSONNodePrint(JSONNode * node) { +JSONNodePrint(JSONNode * node, JSONNode * currNode) { if (node == NULL) return; static int indent; if (node->parent == NULL) indent = 0; - + + if (currNode == node) { + vt100SaveCursor(); + } + switch (node->kind) { case JSONNodeKind_Nul: { printf("null"); break; } + case JSONNodeKind_Int: { + char * str = (char *)node->data; + printf("%s", (str == NULL || strlen(str) == 0) ? "0" : str); + break; + } case JSONNodeKind_Str: { char * str = (char *)node->data; printf("\"%s\"", str == NULL ? "" : str); @@ -171,136 +224,167 @@ JSONNodePrint(JSONNode * node) { } case JSONNodeKind_Obj: { printf("{\n"); - JSONNode * ptr = node->children; + JSONNode * ptr = node->firstChild; indent++; while (ptr != NULL) { - char * key = (char *)ptr->data; - JSONNode * value = ptr->next; Indent(indent); - printf("\"%s\": ", key); - JSONNodePrint(value); - if (ptr->next != NULL) - ptr = ptr->next->next; - else - ptr = NULL; - printf("%s\n", (ptr == NULL ? "" : ",")); + JSONNodePrint(ptr, currNode); + ptr = ptr->next; + + if (ptr != NULL) { + printf(": "); + JSONNodePrint(ptr, currNode); + if (ptr->next != NULL) + printf(","); + ptr = ptr->next; + } + printf("\n"); } indent--; Indent(indent); printf("}"); break; } + case JSONNodeKind_Arr: { + printf("[\n"); + JSONNode * ptr = node->firstChild; + indent++; + while (ptr != NULL) { + Indent(indent); + JSONNodePrint(ptr, currNode); + if (ptr->next != NULL) + printf(","); + printf("\n"); + ptr = ptr->next; + } + indent--; + Indent(indent); + printf("]"); + break; + } } } // Input -JSONNode * g_Node; +JSONNode * g_DrawNode = NULL; +JSONNode * g_CurrNode = NULL; void -Draw(JSONNode * node, const char * str) { +Draw(void) { vt100ClearScreen(); vt100CursorHome(); - printf("> %s\n\n", str); - - if (node != NULL) - JSONNodePrint(node); + if (g_DrawNode != NULL) { + JSONNodePrint(g_DrawNode, g_CurrNode); + vt100RestoreCursor(); + } +} - vt100CursorPos(0, strlen(str) + 3); +int +GetChar() { + Draw(); + int c = getch(); + return c; } -char * -GetStr() { - char * str = NEWARR(char, 16); - int strLen = 0; - int c; - while ((c = getch()), (c != '\r') && (c != '\n')) { - if (strLen < 16 - 1) { - str[strLen++] = c; - str[strLen] = '\0'; - Draw(g_Node, str); - } - } - return str; +int +PeekChar() { + Draw(); + int c = peekch(); + return c; } +typedef bool(*CharPredicateFunc)(char, int); + +bool predStr(char c, int i) { return c >= 'a' && c <= 'z'; } +bool predInt(char c, int i) { return c >= '0' && c <= '9'; } + JSONNode * -GetNode(JSONNode * parent) { - int c = getch(); +GetNode() { + JSONNode * result = NULL; + JSONNode * node = NULL; + int c; + int strLen = 0; - JSONNode * result = JSONNodeNewNul(); - - if (parent == NULL) - g_Node = result; - - if (parent != NULL && result != NULL) - JSONNodeAppend(parent, result); - - switch (c) { - case 's': { - result->kind = JSONNodeKind_Str; - Draw(g_Node, ""); - result->data = (size_t)GetStr(); - Draw(g_Node, ""); - break; - } - case 'o': { - result->kind = JSONNodeKind_Obj; - Draw(g_Node, ""); - while ((c = peekch()), (c != '\r') && (c != '\n')) { - Draw(g_Node, ""); + bool editingNode = false; + + while (true) { + c = GetChar(); + + if (c == 3) + break; - JSONNodeAppend(result, JSONNodeNewStr(GetStr())); - Draw(g_Node, ""); + if (isNewline(c)) { + if (node == NULL || node->parent == NULL) + break; - JSONNodeAppend(result, GetNode(result)); - Draw(g_Node, ""); + editingNode = false; + g_CurrNode = node = node->parent; + + continue; + } + + if (! editingNode) { + JSONNode * old = node; + + /**/ if (c == 'i') { node = JSONNodeNew(JSONNodeKind_Int); editingNode = true; } + else if (c == 's') { node = JSONNodeNew(JSONNodeKind_Str); editingNode = true; } + else if (c == 'o') { node = JSONNodeNew(JSONNodeKind_Obj); } + else if (c == 'a') { node = JSONNodeNew(JSONNodeKind_Arr); } + else if (isBackspace(c) && node != NULL) { + g_CurrNode = node = JSONNodeRemove(node); + continue; + } + else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; continue; } + else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; continue; } + else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; continue; } + else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; continue; } + else { continue; } + + g_CurrNode = node; + + if (old != NULL) + JSONNodePush(old, node); + else + g_DrawNode = result = node; + } + else { + if (node->data == (size_t)NULL) { + node->data = (size_t)NEWARR(char, 16); + strLen = 0; + } + char * str = (char *)node->data; + + if (isBackspace(c)) { + str[strLen-1] = '\0'; + strLen--; + } + else if (strLen < 16 - 1) { + str[strLen] = c; + str[strLen+1] = '\0'; + strLen++; + } } - getch(); - } } return result; } -JSONNode * -TestNode() { - JSONNode * n = JSONNodeNewObj(); - JSONNode * k1 = JSONNodeNewStr("key 1"); - JSONNode * v1 = JSONNodeNewObj(); - JSONNode * k11 = JSONNodeNewStr("key 11"); - JSONNode * v11 = JSONNodeNewStr("val 11"); - JSONNode * k12 = JSONNodeNewStr("key 12"); - JSONNode * v12 = JSONNodeNewStr("val 12"); - JSONNode * k2 = JSONNodeNewStr("key 2"); - JSONNode * v2 = JSONNodeNewStr("val 2"); - - JSONNodeAppend(n, k1); - JSONNodeAppend(n, v1); - JSONNodeAppend(n, k2); - JSONNodeAppend(n, v2); - - JSONNodeAppend(v1, k11); - JSONNodeAppend(v1, v11); - JSONNodeAppend(v1, k12); - JSONNodeAppend(v1, v12); - - return n; -} + + int main() { - Draw(NULL, ""); + vt100EnableAlternateBuffer(); - JSONNode * n = GetNode(NULL); - //JSONNode * n = TestNode(); + JSONNode * n = GetNode(); + + vt100DisableAlternateBuffer(); - vt100ClearScreen(); - vt100CursorHome(); - JSONNodePrint(n); + JSONNodePrint(n, NULL); // JSONFree(n); return 0; -} \ No newline at end of file +}